From de1739cc8483696506829b52e7fda4f6bb195e6a Mon Sep 17 00:00:00 2001 From: Loic Dachary Date: Mon, 10 Apr 2017 08:20:49 +0000 Subject: [PATCH] Merge branch 'wip-signed-integer-overflow-cppcheck' into 'master' Wip signed integer overflow cppcheck Fix for cppcheck signed integer overflow error See merge request !7 --- .gitattributes | 3 + .gitignore | 28 + AUTHORS | 0 COPYING | 37 + ChangeLog | 0 Examples/.gitignore | 9 + Examples/Makefile.am | 67 + Examples/cauchy_01.c | 112 ++ Examples/cauchy_02.c | 272 ++++ Examples/cauchy_03.c | 290 ++++ Examples/cauchy_04.c | 272 ++++ Examples/decoder.c | 397 ++++++ Examples/encode_decode.sh | 21 + Examples/encoder.c | 627 +++++++++ Examples/jerasure_01.c | 92 ++ Examples/jerasure_02.c | 94 ++ Examples/jerasure_03.c | 119 ++ Examples/jerasure_04.c | 118 ++ Examples/jerasure_05.c | 217 +++ Examples/jerasure_06.c | 233 ++++ Examples/jerasure_07.c | 223 ++++ Examples/jerasure_08.c | 232 ++++ Examples/liberation_01.c | 192 +++ Examples/reed_sol_01.c | 195 +++ Examples/reed_sol_02.c | 104 ++ Examples/reed_sol_03.c | 195 +++ Examples/reed_sol_04.c | 120 ++ Examples/reed_sol_test_gf.c | 191 +++ Examples/reed_sol_time_gf.c | 204 +++ Examples/test_all_gfs.sh | 98 ++ Examples/test_galois.c | 23 + Examples/time_all_gfs_argv_init.sh | 64 + License.txt | 37 + Makefile.am | 5 + Manual.pdf | Bin 0 -> 409116 bytes NEWS | 0 PERF.txt | 243 ++++ README | 95 ++ configure.ac | 54 + include/cauchy.h | 54 + include/galois.h | 103 ++ include/jerasure.h | 302 +++++ include/liberation.h | 52 + include/reed_sol.h | 59 + include/timing.h | 43 + m4/ax_check_compile_flag.m4 | 74 ++ m4/ax_ext.m4 | 247 ++++ m4/ax_gcc_x86_avx_xgetbv.m4 | 79 ++ m4/ax_gcc_x86_cpuid.m4 | 79 ++ m4/ax_require_defined.m4 | 37 + src/Makefile.am | 22 + src/cauchy.c | 405 ++++++ src/cauchy_best_r6.c | 1983 ++++++++++++++++++++++++++++ src/galois.c | 377 ++++++ src/jerasure.c | 1485 +++++++++++++++++++++ src/liberation.c | 262 ++++ src/reed_sol.c | 302 +++++ src/timing.c | 63 + 58 files changed, 11311 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 Examples/.gitignore create mode 100644 Examples/Makefile.am create mode 100644 Examples/cauchy_01.c create mode 100644 Examples/cauchy_02.c create mode 100644 Examples/cauchy_03.c create mode 100644 Examples/cauchy_04.c create mode 100644 Examples/decoder.c create mode 100755 Examples/encode_decode.sh create mode 100644 Examples/encoder.c create mode 100644 Examples/jerasure_01.c create mode 100644 Examples/jerasure_02.c create mode 100644 Examples/jerasure_03.c create mode 100644 Examples/jerasure_04.c create mode 100644 Examples/jerasure_05.c create mode 100644 Examples/jerasure_06.c create mode 100644 Examples/jerasure_07.c create mode 100644 Examples/jerasure_08.c create mode 100644 Examples/liberation_01.c create mode 100644 Examples/reed_sol_01.c create mode 100644 Examples/reed_sol_02.c create mode 100644 Examples/reed_sol_03.c create mode 100644 Examples/reed_sol_04.c create mode 100644 Examples/reed_sol_test_gf.c create mode 100644 Examples/reed_sol_time_gf.c create mode 100755 Examples/test_all_gfs.sh create mode 100644 Examples/test_galois.c create mode 100755 Examples/time_all_gfs_argv_init.sh create mode 100644 License.txt create mode 100644 Makefile.am create mode 100644 Manual.pdf create mode 100644 NEWS create mode 100644 PERF.txt create mode 100644 README create mode 100644 configure.ac create mode 100644 include/cauchy.h create mode 100644 include/galois.h create mode 100644 include/jerasure.h create mode 100644 include/liberation.h create mode 100644 include/reed_sol.h create mode 100644 include/timing.h create mode 100644 m4/ax_check_compile_flag.m4 create mode 100644 m4/ax_ext.m4 create mode 100644 m4/ax_gcc_x86_avx_xgetbv.m4 create mode 100644 m4/ax_gcc_x86_cpuid.m4 create mode 100644 m4/ax_require_defined.m4 create mode 100644 src/Makefile.am create mode 100644 src/cauchy.c create mode 100644 src/cauchy_best_r6.c create mode 100644 src/galois.c create mode 100644 src/jerasure.c create mode 100644 src/liberation.c create mode 100644 src/reed_sol.c create mode 100644 src/timing.c diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..f0b7445 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +*.ac eol=lf +*.am eol=lf +*.sh eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6c46716 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +/INSTALL +Makefile +Makefile.in +/aclocal.m4 +/autom4te.cache/ +/autoscan.log +/build-aux/ +/config.log +/config.status +/configure +/configure.scan +.deps/ +/include/config.h +/include/config.h.in +/include/stamp-h1 +.libs/ +/libtool +/m4/libtool.m4 +/m4/ltoptions.m4 +/m4/ltsugar.m4 +/m4/ltversion.m4 +/m4/lt~obsolete.m4 +*.l[ao] +*.[ao] +*~ +.dirstamp +*.log +*.trs diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e69de29 diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..20ffbd2 --- /dev/null +++ b/COPYING @@ -0,0 +1,37 @@ + +Copyright (c) 2013, James S. Plank and Kevin Greenan +All rights reserved. + +Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques + +Revision 2.0: Galois Field backend now links to GF-Complete + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + - Neither the name of the University of Tennessee nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY +WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/Examples/.gitignore b/Examples/.gitignore new file mode 100644 index 0000000..b97ec5a --- /dev/null +++ b/Examples/.gitignore @@ -0,0 +1,9 @@ +/cauchy_[0-9][0-9] +/decoder +/encoder +/jerasure_[0-9][0-9] +/liberation_[0-9][0-9] +/reed_sol_[0-9][0-9] +/reed_sol_test_gf +/reed_sol_time_gf +/test_galois diff --git a/Examples/Makefile.am b/Examples/Makefile.am new file mode 100644 index 0000000..defd139 --- /dev/null +++ b/Examples/Makefile.am @@ -0,0 +1,67 @@ +# Jerasure AM file + +AM_CPPFLAGS = -I$(top_srcdir)/include +AM_CFLAGS = $(SIMD_FLAGS) + +bin_PROGRAMS = jerasure_01 \ + jerasure_02 \ + jerasure_03 \ + jerasure_04 \ + jerasure_05 \ + jerasure_06 \ + jerasure_07 \ + jerasure_08 \ + reed_sol_01 \ + reed_sol_02 \ + reed_sol_03 \ + reed_sol_04 \ + reed_sol_test_gf \ + reed_sol_time_gf \ + cauchy_01 \ + cauchy_02 \ + cauchy_03 \ + cauchy_04 \ + liberation_01 \ + encoder \ + decoder + +check_PROGRAMS = + +TESTS=test_all_gfs.sh encode_decode.sh $(check_PROGRAMS) + +dist_noinst_SCRIPTS = test_all_gfs.sh time_all_gfs_argv_init.sh + +test_galois_SOURCES = test_galois.c +check_PROGRAMS += test_galois + +jerasure_01_SOURCES = jerasure_01.c +jerasure_02_SOURCES = jerasure_02.c +jerasure_03_SOURCES = jerasure_03.c +jerasure_04_SOURCES = jerasure_04.c +jerasure_05_SOURCES = jerasure_05.c +jerasure_06_SOURCES = jerasure_06.c +jerasure_07_SOURCES = jerasure_07.c +jerasure_08_SOURCES = jerasure_08.c + +reed_sol_01_SOURCES = reed_sol_01.c +reed_sol_02_SOURCES = reed_sol_02.c +reed_sol_03_SOURCES = reed_sol_03.c +reed_sol_04_SOURCES = reed_sol_04.c + +reed_sol_test_gf_SOURCES = reed_sol_test_gf.c +reed_sol_time_gf_SOURCES = reed_sol_time_gf.c + +cauchy_01_SOURCES = cauchy_01.c +cauchy_02_SOURCES = cauchy_02.c +cauchy_03_SOURCES = cauchy_03.c +cauchy_04_SOURCES = cauchy_04.c + +liberation_01_SOURCES = liberation_01.c + +decoder_SOURCES = decoder.c +encoder_SOURCES = encoder.c + +LDADD = ../src/libJerasure.la +decoder_LDADD = $(LDADD) ../src/libtiming.a +encoder_LDADD = $(LDADD) ../src/libtiming.a +reed_sol_time_gf_LDADD = $(LDADD) ../src/libtiming.a diff --git a/Examples/cauchy_01.c b/Examples/cauchy_01.c new file mode 100644 index 0000000..65419a0 --- /dev/null +++ b/Examples/cauchy_01.c @@ -0,0 +1,112 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank + */ + +#include +#include +#include +#include +#include "cauchy.h" +#include "jerasure.h" +#include "reed_sol.h" + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +static void usage(char *s) +{ + fprintf(stderr, "usage: cauchy_01 n w - Converts the value n to a bitmatrix using GF(2^w).\n"); + fprintf(stderr, " \n"); + fprintf(stderr, " It prints the bitmatrix, and reports on the numberof ones.\n"); + fprintf(stderr, " Use 0x to input n in hexadecimal.\n"); + fprintf(stderr, " W must be <= 32.\n"); + fprintf(stderr, " \n"); + fprintf(stderr, "This demonstrates: cauchy_n_ones()\n"); + fprintf(stderr, " jerasure_matrix_to_bitmatrix()\n"); + fprintf(stderr, " jerasure_print_bitmatrix()\n"); + if (s != NULL) fprintf(stderr, "\n%s\n", s); + exit(1); +} + +int main(int argc, char **argv) +{ + int n; + int i, no, w; + int *bitmatrix; + + if (argc != 3) usage(NULL); + if (sscanf(argv[1], "0x%x", &n) == 0) { + if (sscanf(argv[1], "%d", &n) == 0) usage("Bad n"); + } + if (sscanf(argv[2], "%d", &w) == 0 || w <= 0 || w > 32) usage("Bad w"); + if (w == 31) { + if (n & 0x80000000L) usage("Bad n/w combination (n not between 0 and 2^w-1)\n"); + } else if (w < 31) { + if (n >= (1 << w)) usage("Bad n/w combination (n not between 0 and 2^w-1)\n"); + } + + bitmatrix = jerasure_matrix_to_bitmatrix(1, 1, w, &n); + printf("cauchy_01 %u %d\n", w, n); + printf("

cauchy_01 %u %d

\n", w, n); + printf("
\n");
+  if (w == 32) {
+    printf("Converted the value 0x%x to the following bitmatrix:\n\n", n);
+  } else {
+    printf("Converted the value %d (0x%x) to the following bitmatrix:\n\n", n, n);
+  }
+  jerasure_print_bitmatrix(bitmatrix, w, w, w);
+  printf("\n");
+
+  no = 0;
+  for (i = 0; i < w*w; i++) no += bitmatrix[i];
+  if (no != cauchy_n_ones(n, w)) { 
+    fprintf(stderr, "Jerasure error: # ones in the bitmatrix (%d) doesn't match cauchy_n_ones() (%d).\n",
+       no, cauchy_n_ones(n, w));
+    exit(1);
+  }
+
+  printf("# Ones: %d\n", cauchy_n_ones(n, w));
+
+  return 0;
+}
diff --git a/Examples/cauchy_02.c b/Examples/cauchy_02.c
new file mode 100644
index 0000000..45c78ab
--- /dev/null
+++ b/Examples/cauchy_02.c
@@ -0,0 +1,272 @@
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Jerasure's authors:
+ 
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "jerasure.h"
+#include "cauchy.h"
+
+#define talloc(type, num) (type *) malloc(sizeof(type)*(num))
+
+static void usage(char *s)
+{
+  fprintf(stderr, "usage: cauchy_02 k m w seed - CRS coding example using Bloemer's original matrix.\n");
+  fprintf(stderr, "       \n");
+  fprintf(stderr, "k+m must be <= 2^w\n");
+  fprintf(stderr, "This sets up a generator matrix (G^T) in GF(2^w) whose last m rows are\n");
+  fprintf(stderr, "created from a Cauchy matrix, using the original definition from [Bloemer95].\n");
+  fprintf(stderr, "It converts this matrix to a bitmatrix, and then it encodes w packets from\n");
+  fprintf(stderr, "each of k disks (simulated) onto w packets on each of m disks.  Packets are \n");
+  fprintf(stderr, "simply longs.  Then, it deletes m random disks, and decodes.  \n");
+  fprintf(stderr, "\n");
+  fprintf(stderr, "The encoding and decoding are done twice, first, with jerasure_bitmatrix_encode()\n");
+  fprintf(stderr, "and jerasure_bitmatrix_decode(), and second using 'smart' scheduling with\n");
+  fprintf(stderr, "jerasure_schedule_encode() and jerasure_schedule_decode_lazy().\n");
+
+  fprintf(stderr, "\n");
+  fprintf(stderr, "This demonstrates: cauchy_original_coding_matrix()\n");
+  fprintf(stderr, "                   jerasure_bitmatrix_encode()\n");
+  fprintf(stderr, "                   jerasure_bitmatrix_decode()\n");
+  fprintf(stderr, "                   cauchy_n_ones()\n");
+  fprintf(stderr, "                   jerasure_smart_bitmatrix_to_schedule()\n");
+  fprintf(stderr, "                   jerasure_schedule_encode()\n");
+  fprintf(stderr, "                   jerasure_schedule_decode_lazy()\n");
+  fprintf(stderr, "                   jerasure_print_matrix()\n");
+  fprintf(stderr, "                   jerasure_print_bitmatrix()\n");
+  fprintf(stderr, "                   jerasure_get_stats()\n");
+  if (s != NULL) fprintf(stderr, "%s\n", s);
+  exit(1);
+}
+
+static void print_array(char **ptrs, int ndevices, int size, int packetsize, char *label)
+{
+  int i, j, x;
+  unsigned char *up;
+
+  printf("
\n"); + + for (i = 0; i < ndevices; i++) printf("\n", label, i); + printf("\n"); + printf("\n"); + for (i = 0; i < ndevices; i++) { + printf("\n"); + } + printf("
%s%x
");
+  for (j = 0; j < size/packetsize; j++) printf("Packet %d\n", j);
+  printf("
");
+    up = (unsigned char *) ptrs[i];
+    for (j = 0; j < size/packetsize; j++) {
+      for (x = 0; x < packetsize; x++) {
+        if (x > 0 && x%4 == 0) printf(" ");
+        printf("%02x", up[j*packetsize+x]);
+      }
+      printf("\n");
+    }
+    printf("
\n"); +} + +int main(int argc, char **argv) +{ + int k, w, i, m; + int *matrix, *bitmatrix, **schedule; + char **data, **coding, **dcopy, **ccopy; + int no; + int *erasures, *erased; + double mstats[3], sstats[3]; + uint32_t seed; + + if (argc != 5) usage(NULL); + if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k"); + if (sscanf(argv[2], "%d", &m) == 0 || m <= 0) usage("Bad m"); + if (sscanf(argv[3], "%d", &w) == 0 || w <= 0 || w > 32) usage("Bad w"); + if (sscanf(argv[4], "%d", &seed) == 0) usage("Bad seed"); + if (w < 30 && (k+m) > (1 << w)) usage("k + m is too big"); + + matrix = cauchy_original_coding_matrix(k, m, w); + if (matrix == NULL) { + usage("couldn't make coding matrix"); + } + + /* Print out header information to the output file. */ + printf("\n"); + printf("Jerasure Example Output: cauchy_02 %d %d %d %d\n", k, m, w, seed); + printf("

Jerasure Example Output: cauchy_02 %d %d %d %d

\n", k, m, w, seed); + + printf("
\n"); + printf("Parameters:\n"); + printf("
  • Number of data disks (k): %d\n", k); + printf("
  • Number of coding disks (m): %d\n", m); + printf("
  • Word size of the Galois Field: (w): %d\n", w); + printf("
  • Seed for the random number generator: %d\n", seed); + printf("
  • Number of bytes stored per disk: %ld\n", sizeof(long)*w); + printf("
  • Number of packets stored per disk: %d\n", w); + printf("
  • Number of bytes per packet: %ld\n", sizeof(long)); + printf("
\n"); + + /* Print out the matrix and the bitmatrix */ + printf("
\n"); + printf("Here is the matrix, which was created with cauchy_original_coding_matrix().\n"); + printf("This is not the best matrix to use, but we include it to show an example\n"); + printf("of cauchy_original_coding_matrix(). For the best matrix and encoding/decoding\n"); + printf("methodology, see cauchy_04.

\n");
+
+  jerasure_print_matrix(matrix, m, k, w);
+  printf("
\n"); + + bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix); + + no = 0; + for (i = 0; i < k*m; i++) { + no += cauchy_n_ones(matrix[i], w); + } + + printf("The bitmatrix, which has %d one%s:

\n", no, (no == 1) ? "" : "s");
+  jerasure_print_bitmatrix(bitmatrix, m*w, k*w, w);
+  printf("
\n"); + printf("
\n"); + MOA_Seed(seed); + + data = talloc(char *, k); + dcopy = talloc(char *, k); + for (i = 0; i < k; i++) { + data[i] = talloc(char, sizeof(long)*w); + dcopy[i] = talloc(char, sizeof(long)*w); + MOA_Fill_Random_Region(data[i], sizeof(long)*w); + memcpy(dcopy[i], data[i], sizeof(long)*w); + } + + printf("Here are the packets on the data disks:

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + + coding = talloc(char *, m); + ccopy = talloc(char *, m); + for (i = 0; i < m; i++) { + coding[i] = talloc(char, sizeof(long)*w); + ccopy[i] = talloc(char, sizeof(long)*w); + } + + jerasure_bitmatrix_encode(k, m, w, bitmatrix, data, coding, w*sizeof(long), sizeof(long)); + jerasure_get_stats(mstats); + + schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix); + jerasure_schedule_encode(k, m, w, schedule, data, ccopy, w*sizeof(long), sizeof(long)); + jerasure_get_stats(sstats); + + printf("

Encoding with jerasure_bitmatrix_encode() - Bytes XOR'd: %.0lf.
\n", mstats[0]); + printf("Encoding with jerasure_schedule_encode() - Bytes XOR'd: %.0lf.
\n", sstats[0]); + + for (i = 0; i < m; i++) { + if (memcmp(coding[i], ccopy[i], sizeof(long)*w) != 0) { + printf("Problem: the two encodings don't match on disk C%x\n", i); + exit(0); + } + } + + printf("Here are the packets on the coding disks.
\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + erasures = talloc(int, (m+1)); + erased = talloc(int, (k+m)); + for (i = 0; i < m+k; i++) erased[i] = 0; + for (i = 0; i < m; ) { + erasures[i] = MOA_Random_W(31, 1)%(k+m); + if (erased[erasures[i]] == 0) { + erased[erasures[i]] = 1; + bzero((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], sizeof(long)*w); + i++; + } + } + erasures[i] = -1; + printf("Erasures on the following devices:"); + for (i = 0; erasures[i] != -1; i++) { + printf(" %c%x", ((erasures[i] < k) ? 'D' : 'C'), (erasures[i] < k ? erasures[i] : erasures[i]-k)); + } + printf("
\nHere is the state of the system:\n

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + jerasure_bitmatrix_decode(k, m, w, bitmatrix, 0, erasures, data, coding, w*sizeof(long), sizeof(long)); + jerasure_get_stats(mstats); + + printf("

Decoded with jerasure_bitmatrix_decode - Bytes XOR'd: %.0lf.
\n", mstats[0]); + + for (i = 0; i < k; i++) if (memcmp(data[i], dcopy[i], sizeof(long)*w) != 0) { + printf("ERROR: D%x after decoding does not match its state before decoding!
\n", i); + } + for (i = 0; i < m; i++) if (memcmp(coding[i], ccopy[i], sizeof(long)*w) != 0) { + printf("ERROR: C%x after decoding does not match its state before decoding!
\n", i); + } + + for (i = 0; erasures[i] != -1; i++) { + bzero((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], sizeof(long)*w); + } + + jerasure_schedule_decode_lazy(k, m, w, bitmatrix, erasures, data, coding, w*sizeof(long), sizeof(long), 1); + jerasure_get_stats(sstats); + + printf("jerasure_schedule_decode_lazy - Bytes XOR'd: %.0lf.
\n", sstats[0]); + + for (i = 0; i < k; i++) if (memcmp(data[i], dcopy[i], sizeof(long)*w) != 0) { + printf("ERROR: D%x after decoding does not match its state before decoding!
\n", i); + } + for (i = 0; i < m; i++) if (memcmp(coding[i], ccopy[i], sizeof(long)*w) != 0) { + printf("ERROR: C%x after decoding does not match its state before decoding!
\n", i); + } + + printf("Here is the state of the system:\n

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + return 0; +} diff --git a/Examples/cauchy_03.c b/Examples/cauchy_03.c new file mode 100644 index 0000000..e246e77 --- /dev/null +++ b/Examples/cauchy_03.c @@ -0,0 +1,290 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank + */ + +#include +#include +#include +#include +#include +#include "jerasure.h" +#include "cauchy.h" + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +static void usage(char *s) +{ + fprintf(stderr, "usage: cauchy_03 k m w seed - CRS coding example improving the matrix.\n"); + fprintf(stderr, " \n"); + fprintf(stderr, "k+m must be <= 2^w\n"); + fprintf(stderr, "This sets up a generator matrix (G^T) in GF(2^w) whose last m rows are\n"); + fprintf(stderr, "created from a Cauchy matrix, using the original definition from [Bloemer95].\n"); + fprintf(stderr, "This is done with cauchy_xy_coding_matrix().\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "It then it improves the matrix, which yields a different bitmatrix that is\n"); + fprintf(stderr, "MDS like the original bitmatrix, but it will yield a bitmatrix with fewer ones.\n"); + fprintf(stderr, "Then, it encodes w packets from each of k disks (simulated) onto w packets on\n"); + fprintf(stderr, "on each of m disks. Packets are longs. Then, it deletes m random disks, and decodes.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The encoding and decoding are done twice, first, with jerasure_bitmatrix_encode()\n"); + fprintf(stderr, "and jerasure_bitmatrix_decode(), and second using 'smart' scheduling with\n"); + fprintf(stderr, "jerasure_schedule_encode() and jerasure_schedule_decode_lazy().\n"); + + fprintf(stderr, "\n"); + fprintf(stderr, "This demonstrates: cauchy_xy_coding_matrix()\n"); + fprintf(stderr, " cauchy_improve_coding_matrix()\n"); + fprintf(stderr, " jerasure_bitmatrix_encode()\n"); + fprintf(stderr, " jerasure_bitmatrix_decode()\n"); + fprintf(stderr, " cauchy_n_ones()\n"); + fprintf(stderr, " jerasure_smart_bitmatrix_to_schedule()\n"); + fprintf(stderr, " jerasure_schedule_encode()\n"); + fprintf(stderr, " jerasure_schedule_decode_lazy()\n"); + fprintf(stderr, " jerasure_print_matrix()\n"); + fprintf(stderr, " jerasure_print_bitmatrix()\n"); + fprintf(stderr, " jerasure_get_stats()\n"); + if (s != NULL) fprintf(stderr, "%s\n", s); + exit(1); +} + +static void print_array(char **ptrs, int ndevices, int size, int packetsize, char *label) +{ + int i, j, x; + unsigned char *up; + + printf("
\n"); + + for (i = 0; i < ndevices; i++) printf("\n", label, i); + printf("\n"); + printf("\n"); + for (i = 0; i < ndevices; i++) { + printf("\n"); + } + printf("
%s%x
");
+  for (j = 0; j < size/packetsize; j++) printf("Packet %d\n", j);
+  printf("
");
+    up = (unsigned char *) ptrs[i];
+    for (j = 0; j < size/packetsize; j++) {
+      for (x = 0; x < packetsize; x++) {
+        if (x > 0 && x%4 == 0) printf(" ");
+        printf("%02x", up[j*packetsize+x]);
+      }
+      printf("\n");
+    }
+    printf("
\n"); +} + +int main(int argc, char **argv) +{ + int k, w, i, m; + int *matrix, *bitmatrix, **schedule; + char **data, **coding, **dcopy, **ccopy; + int no; + int *erasures, *erased; + double mstats[3], sstats[3]; + uint32_t seed; + int *X, *Y; + + if (argc != 5) usage(NULL); + if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k"); + if (sscanf(argv[2], "%d", &m) == 0 || m <= 0) usage("Bad m"); + if (sscanf(argv[3], "%d", &w) == 0 || w <= 0 || w > 32) usage("Bad w"); + if (sscanf(argv[4], "%d", &seed) == 0) usage("Bad seed"); + if (w < 30 && (k+m) > (1 << w)) usage("k + m is too big"); + + X = talloc(int, m); + Y = talloc(int, k); + for (i = 0; i < m; i++) X[i] = i; + for (i = 0; i < k; i++) Y[i] = m+i; + + matrix = cauchy_xy_coding_matrix(k, m, w, X, Y); + if (matrix == NULL) { + usage("couldn't make coding matrix"); + } + + /* Print out header information to the output file. */ + printf("\n"); + printf("Jerasure Example Output: cauchy_03 %d %d %d %d\n", k, m, w, seed); + printf("

Jerasure Example Output: cauchy_03 %d %d %d %d

\n", k, m, w, seed); + + printf("
\n"); + printf("Parameters:\n"); + printf("
  • Number of data disks (k): %d\n", k); + printf("
  • Number of coding disks (m): %d\n", m); + printf("
  • Word size of the Galois Field: (w): %d\n", w); + printf("
  • Seed for the random number generator: %d\n", seed); + printf("
  • Number of bytes stored per disk: %ld\n", sizeof(long)*w); + printf("
  • Number of packets stored per disk: %d\n", w); + printf("
  • Number of bytes per packet: %ld\n", sizeof(long)); + printf("
\n"); + + /* Print out the matrix and the bitmatrix */ + printf("
\n"); + printf("Here is the matrix, which was created with cauchy_xy_coding_matrix().\n"); + + printf("
\n");
+  jerasure_print_matrix(matrix, m, k, w);
+  printf("
\n"); + + cauchy_improve_coding_matrix(k, m, w, matrix); + + printf("
\n"); + printf("Here is the matrix improved with cauchy_improve_coding_matrix().\n"); + + printf("
\n");
+  jerasure_print_matrix(matrix, m, k, w);
+  printf("
\n"); + + bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix); + + no = 0; + for (i = 0; i < k*m; i++) { + no += cauchy_n_ones(matrix[i], w); + } + + printf("The bitmatrix, which has %d one%s:

\n", no, (no == 1) ? "" : "s");
+  jerasure_print_bitmatrix(bitmatrix, m*w, k*w, w);
+  printf("
\n"); + printf("
\n"); + + MOA_Seed(seed); + + data = talloc(char *, k); + dcopy = talloc(char *, k); + for (i = 0; i < k; i++) { + data[i] = talloc(char, sizeof(long)*w); + dcopy[i] = talloc(char, sizeof(long)*w); + MOA_Fill_Random_Region(data[i], sizeof(long)*w); + memcpy(dcopy[i], data[i], sizeof(long)*w); + } + + printf("Here are the packets on the data disks:

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + + coding = talloc(char *, m); + ccopy = talloc(char *, m); + for (i = 0; i < m; i++) { + coding[i] = talloc(char, sizeof(long)*w); + ccopy[i] = talloc(char, sizeof(long)*w); + } + + jerasure_bitmatrix_encode(k, m, w, bitmatrix, data, coding, w*sizeof(long), sizeof(long)); + jerasure_get_stats(mstats); + + schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix); + jerasure_schedule_encode(k, m, w, schedule, data, ccopy, w*sizeof(long), sizeof(long)); + jerasure_get_stats(sstats); + + printf("

Encoding with jerasure_bitmatrix_encode() - Bytes XOR'd: %.0lf.
\n", mstats[0]); + printf("Encoding with jerasure_schedule_encode() - Bytes XOR'd: %.0lf.
\n", sstats[0]); + + for (i = 0; i < m; i++) { + if (memcmp(coding[i], ccopy[i], sizeof(long)*w) != 0) { + printf("Problem: the two encodings don't match on disk C%x\n", i); + exit(0); + } + } + + printf("Here are the packets on the coding disks.
\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + erasures = talloc(int, (m+1)); + erased = talloc(int, (k+m)); + for (i = 0; i < m+k; i++) erased[i] = 0; + for (i = 0; i < m; ) { + erasures[i] = MOA_Random_W(31, 1)%(k+m); + if (erased[erasures[i]] == 0) { + erased[erasures[i]] = 1; + bzero((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], sizeof(long)*w); + i++; + } + } + erasures[i] = -1; + printf("Erasures on the following devices:"); + for (i = 0; erasures[i] != -1; i++) { + printf(" %c%x", ((erasures[i] < k) ? 'D' : 'C'), (erasures[i] < k ? erasures[i] : erasures[i]-k)); + } + printf("
\nHere is the state of the system:\n

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + jerasure_bitmatrix_decode(k, m, w, bitmatrix, 0, erasures, data, coding, w*sizeof(long), sizeof(long)); + jerasure_get_stats(mstats); + + printf("

Decoded with jerasure_bitmatrix_decode - Bytes XOR'd: %.0lf.
\n", mstats[0]); + + for (i = 0; i < k; i++) if (memcmp(data[i], dcopy[i], sizeof(long)*w) != 0) { + printf("ERROR: D%x after decoding does not match its state before decoding!
\n", i); + } + for (i = 0; i < m; i++) if (memcmp(coding[i], ccopy[i], sizeof(long)*w) != 0) { + printf("ERROR: C%x after decoding does not match its state before decoding!
\n", i); + } + + for (i = 0; erasures[i] != -1; i++) { + bzero((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], sizeof(long)*w); + } + + jerasure_schedule_decode_lazy(k, m, w, bitmatrix, erasures, data, coding, w*sizeof(long), sizeof(long), 1); + jerasure_get_stats(sstats); + + printf("jerasure_schedule_decode_lazy - Bytes XOR'd: %.0lf.
\n", sstats[0]); + + for (i = 0; i < k; i++) if (memcmp(data[i], dcopy[i], sizeof(long)*w) != 0) { + printf("ERROR: D%x after decoding does not match its state before decoding!
\n", i); + } + for (i = 0; i < m; i++) if (memcmp(coding[i], ccopy[i], sizeof(long)*w) != 0) { + printf("ERROR: C%x after decoding does not match its state before decoding!
\n", i); + } + + printf("Here is the state of the system:\n

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + return 0; +} diff --git a/Examples/cauchy_04.c b/Examples/cauchy_04.c new file mode 100644 index 0000000..f61c614 --- /dev/null +++ b/Examples/cauchy_04.c @@ -0,0 +1,272 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan. + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank. + */ + +#include +#include +#include +#include +#include +#include "jerasure.h" +#include "cauchy.h" + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +static void usage(char *s) +{ + fprintf(stderr, "usage: cauchy_04 k m w seed - CRS coding example improving the matrix.\n"); + fprintf(stderr, " \n"); + fprintf(stderr, "k+m must be <= 2^w\n"); + fprintf(stderr, "This sets up a generator matrix (G^T) in GF(2^w) whose last m rows are\n"); + fprintf(stderr, "a 'good' matrix, created with cauchy_good_general_coding_matrix().\n"); + fprintf(stderr, "It converts this matrix to a bitmatrix.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Then, it encodes w packets from each of k disks (simulated) onto w packets on\n"); + fprintf(stderr, "on each of m disks. Packets are longs. Then, it deletes m random disks, and decodes.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The encoding and decoding are done twice, first, with jerasure_bitmatrix_encode()\n"); + fprintf(stderr, "and jerasure_bitmatrix_decode(), and second using 'smart' scheduling with\n"); + fprintf(stderr, "jerasure_schedule_encode() and jerasure_schedule_decode_lazy().\n"); + + fprintf(stderr, "\n"); + fprintf(stderr, "This demonstrates: cauchy_good_general_coding_matrix()\n"); + fprintf(stderr, " jerasure_bitmatrix_encode()\n"); + fprintf(stderr, " jerasure_bitmatrix_decode()\n"); + fprintf(stderr, " cauchy_n_ones()\n"); + fprintf(stderr, " jerasure_smart_bitmatrix_to_schedule()\n"); + fprintf(stderr, " jerasure_schedule_encode()\n"); + fprintf(stderr, " jerasure_schedule_decode_lazy()\n"); + fprintf(stderr, " jerasure_print_matrix()\n"); + fprintf(stderr, " jerasure_print_bitmatrix()\n"); + fprintf(stderr, " jerasure_get_stats()\n"); + if (s != NULL) fprintf(stderr, "%s\n", s); + exit(1); +} + +static void print_array(char **ptrs, int ndevices, int size, int packetsize, char *label) +{ + int i, j, x; + unsigned char *up; + + printf("
\n"); + + for (i = 0; i < ndevices; i++) printf("\n", label, i); + printf("\n"); + printf("\n"); + for (i = 0; i < ndevices; i++) { + printf("\n"); + } + printf("
%s%x
");
+  for (j = 0; j < size/packetsize; j++) printf("Packet %d\n", j);
+  printf("
");
+    up = (unsigned char *) ptrs[i];
+    for (j = 0; j < size/packetsize; j++) {
+      for (x = 0; x < packetsize; x++) {
+        if (x > 0 && x%4 == 0) printf(" ");
+        printf("%02x", up[j*packetsize+x]);
+      }
+      printf("\n");
+    }
+    printf("
\n"); +} + +int main(int argc, char **argv) +{ + int k, w, i, m; + int *matrix, *bitmatrix, **schedule; + char **data, **coding, **dcopy, **ccopy; + int no; + int *erasures, *erased; + double mstats[3], sstats[3]; + uint32_t seed; + + if (argc != 5) usage(NULL); + if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k"); + if (sscanf(argv[2], "%d", &m) == 0 || m <= 0) usage("Bad m"); + if (sscanf(argv[3], "%d", &w) == 0 || w <= 0 || w > 32) usage("Bad w"); + if (sscanf(argv[4], "%d", &seed) == 0) usage("Bad seed"); + if (w < 30 && (k+m) > (1 << w)) usage("k + m is too big"); + + matrix = cauchy_good_general_coding_matrix(k, m, w); + if (matrix == NULL) { + usage("couldn't make coding matrix"); + } + + /* Print out header information to the output file. */ + printf("\n"); + printf("Jerasure Example Output: cauchy_04 %d %d %d %d\n", k, m, w, seed); + printf("

Jerasure Example Output: cauchy_04 %d %d %d %d

\n", k, m, w, seed); + + printf("
\n"); + printf("Parameters:\n"); + printf("
  • Number of data disks (k): %d\n", k); + printf("
  • Number of coding disks (m): %d\n", m); + printf("
  • Word size of the Galois Field: (w): %d\n", w); + printf("
  • Seed for the random number generator: %d\n", seed); + printf("
  • Number of bytes stored per disk: %ld\n", sizeof(long)*w); + printf("
  • Number of packets stored per disk: %d\n", w); + printf("
  • Number of bytes per packet: %ld\n", sizeof(long)); + printf("
\n"); + + /* Print out the matrix and the bitmatrix */ + printf("
\n"); + printf("Here is the matrix, which was created with cauchy_good_general_coding_matrix().\n"); + + printf("
\n");
+  jerasure_print_matrix(matrix, m, k, w);
+  printf("
\n"); + + bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix); + + no = 0; + for (i = 0; i < k*m; i++) { + no += cauchy_n_ones(matrix[i], w); + } + + printf("The bitmatrix, which has %d one%s:

\n", no, (no == 1) ? "" : "s");
+  jerasure_print_bitmatrix(bitmatrix, m*w, k*w, w);
+  printf("
\n"); + printf("
\n"); + + MOA_Seed(seed); + + data = talloc(char *, k); + dcopy = talloc(char *, k); + for (i = 0; i < k; i++) { + data[i] = talloc(char, sizeof(long)*w); + dcopy[i] = talloc(char, sizeof(long)*w); + MOA_Fill_Random_Region(data[i], sizeof(long)*w); + memcpy(dcopy[i], data[i], sizeof(long)*w); + } + + printf("Here are the packets on the data disks:

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + + coding = talloc(char *, m); + ccopy = talloc(char *, m); + for (i = 0; i < m; i++) { + coding[i] = talloc(char, sizeof(long)*w); + ccopy[i] = talloc(char, sizeof(long)*w); + } + + jerasure_bitmatrix_encode(k, m, w, bitmatrix, data, coding, w*sizeof(long), sizeof(long)); + jerasure_get_stats(mstats); + + schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix); + jerasure_schedule_encode(k, m, w, schedule, data, ccopy, w*sizeof(long), sizeof(long)); + jerasure_get_stats(sstats); + + printf("

Encoding with jerasure_bitmatrix_encode() - Bytes XOR'd: %.0lf.
\n", mstats[0]); + printf("Encoding with jerasure_schedule_encode() - Bytes XOR'd: %.0lf.
\n", sstats[0]); + + for (i = 0; i < m; i++) { + if (memcmp(coding[i], ccopy[i], sizeof(long)*w) != 0) { + printf("Problem: the two encodings don't match on disk C%x\n", i); + exit(0); + } + } + + printf("Here are the packets on the coding disks.
\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + erasures = talloc(int, (m+1)); + erased = talloc(int, (k+m)); + for (i = 0; i < m+k; i++) erased[i] = 0; + for (i = 0; i < m; ) { + erasures[i] = MOA_Random_W(31, 1)%(k+m); + if (erased[erasures[i]] == 0) { + erased[erasures[i]] = 1; + bzero((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], sizeof(long)*w); + i++; + } + } + erasures[i] = -1; + printf("Erasures on the following devices:"); + for (i = 0; erasures[i] != -1; i++) { + printf(" %c%x", ((erasures[i] < k) ? 'D' : 'C'), (erasures[i] < k ? erasures[i] : erasures[i]-k)); + } + printf("
\nHere is the state of the system:\n

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + jerasure_bitmatrix_decode(k, m, w, bitmatrix, 0, erasures, data, coding, w*sizeof(long), sizeof(long)); + jerasure_get_stats(mstats); + + printf("

Decoded with jerasure_bitmatrix_decode - Bytes XOR'd: %.0lf.
\n", mstats[0]); + + for (i = 0; i < k; i++) if (memcmp(data[i], dcopy[i], sizeof(long)*w) != 0) { + printf("ERROR: D%x after decoding does not match its state before decoding!
\n", i); + } + for (i = 0; i < m; i++) if (memcmp(coding[i], ccopy[i], sizeof(long)*w) != 0) { + printf("ERROR: C%x after decoding does not match its state before decoding!
\n", i); + } + + for (i = 0; erasures[i] != -1; i++) { + bzero((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], sizeof(long)*w); + } + + jerasure_schedule_decode_lazy(k, m, w, bitmatrix, erasures, data, coding, w*sizeof(long), sizeof(long), 1); + jerasure_get_stats(sstats); + + printf("jerasure_schedule_decode_lazy - Bytes XOR'd: %.0lf.
\n", sstats[0]); + + for (i = 0; i < k; i++) if (memcmp(data[i], dcopy[i], sizeof(long)*w) != 0) { + printf("ERROR: D%x after decoding does not match its state before decoding!
\n", i); + } + for (i = 0; i < m; i++) if (memcmp(coding[i], ccopy[i], sizeof(long)*w) != 0) { + printf("ERROR: C%x after decoding does not match its state before decoding!
\n", i); + } + + printf("Here is the state of the system:\n

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + return 0; +} diff --git a/Examples/decoder.c b/Examples/decoder.c new file mode 100644 index 0000000..229dccc --- /dev/null +++ b/Examples/decoder.c @@ -0,0 +1,397 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan. + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank. + */ + +/* +This program takes as input an inputfile, k, m, a coding +technique, w, and packetsize. It is the companion program +of encoder.c, which creates k+m files. This program assumes +that up to m erasures have occurred in the k+m files. It +reads in the k+m files or marks the file as erased. It then +recreates the original file and creates a new file with the +suffix "decoded" with the decoded contents of the file. + +This program does not error check command line arguments because +it is assumed that encoder.c has been called previously with the +same arguments, and encoder.c does error check. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jerasure.h" +#include "reed_sol.h" +#include "galois.h" +#include "cauchy.h" +#include "liberation.h" +#include "timing.h" + +#define N 10 + +enum Coding_Technique {Reed_Sol_Van, Reed_Sol_R6_Op, Cauchy_Orig, Cauchy_Good, Liberation, Blaum_Roth, Liber8tion, RDP, EVENODD, No_Coding}; + +char *Methods[N] = {"reed_sol_van", "reed_sol_r6_op", "cauchy_orig", "cauchy_good", "liberation", "blaum_roth", "liber8tion", "rdp", "evenodd", "no_coding"}; + +/* Global variables for signal handler */ +enum Coding_Technique method; +int readins, n; + +/* Function prototype */ +void ctrl_bs_handler(int dummy); + +int main (int argc, char **argv) { + FILE *fp; // File pointer + + /* Jerasure arguments */ + char **data; + char **coding; + int *erasures; + int *erased; + int *matrix; + int *bitmatrix; + + /* Parameters */ + int k, m, w, packetsize, buffersize; + int tech; + char *c_tech; + + int i, j; // loop control variable, s + int blocksize = 0; // size of individual files + int origsize; // size of file before padding + int total; // used to write data, not padding to file + struct stat status; // used to find size of individual files + int numerased; // number of erased files + + /* Used to recreate file names */ + char *temp; + char *cs1, *cs2, *extension; + char *fname; + int md; + char *curdir; + + /* Used to time decoding */ + struct timing t1, t2, t3, t4; + double tsec; + double totalsec; + + + signal(SIGQUIT, ctrl_bs_handler); + + matrix = NULL; + bitmatrix = NULL; + totalsec = 0.0; + + /* Start timing */ + timing_set(&t1); + + /* Error checking parameters */ + if (argc != 2) { + fprintf(stderr, "usage: inputfile\n"); + exit(0); + } + curdir = (char *)malloc(sizeof(char)*1000); + assert(curdir == getcwd(curdir, 1000)); + + /* Begin recreation of file names */ + cs1 = (char*)malloc(sizeof(char)*strlen(argv[1])); + cs2 = strrchr(argv[1], '/'); + if (cs2 != NULL) { + cs2++; + strcpy(cs1, cs2); + } + else { + strcpy(cs1, argv[1]); + } + cs2 = strchr(cs1, '.'); + if (cs2 != NULL) { + extension = strdup(cs2); + *cs2 = '\0'; + } else { + extension = strdup(""); + } + fname = (char *)malloc(sizeof(char*)*(100+strlen(argv[1])+20)); + + /* Read in parameters from metadata file */ + sprintf(fname, "%s/Coding/%s_meta.txt", curdir, cs1); + + fp = fopen(fname, "rb"); + if (fp == NULL) { + fprintf(stderr, "Error: no metadata file %s\n", fname); + exit(1); + } + temp = (char *)malloc(sizeof(char)*(strlen(argv[1])+20)); + if (fscanf(fp, "%s", temp) != 1) { + fprintf(stderr, "Metadata file - bad format\n"); + exit(0); + } + + if (fscanf(fp, "%d", &origsize) != 1) { + fprintf(stderr, "Original size is not valid\n"); + exit(0); + } + if (fscanf(fp, "%d %d %d %d %d", &k, &m, &w, &packetsize, &buffersize) != 5) { + fprintf(stderr, "Parameters are not correct\n"); + exit(0); + } + c_tech = (char *)malloc(sizeof(char)*(strlen(argv[1])+20)); + if (fscanf(fp, "%s", c_tech) != 1) { + fprintf(stderr, "Metadata file - bad format\n"); + exit(0); + } + if (fscanf(fp, "%d", &tech) != 1) { + fprintf(stderr, "Metadata file - bad format\n"); + exit(0); + } + method = tech; + if (fscanf(fp, "%d", &readins) != 1) { + fprintf(stderr, "Metadata file - bad format\n"); + exit(0); + } + fclose(fp); + + /* Allocate memory */ + erased = (int *)malloc(sizeof(int)*(k+m)); + for (i = 0; i < k+m; i++) + erased[i] = 0; + erasures = (int *)malloc(sizeof(int)*(k+m)); + + data = (char **)malloc(sizeof(char *)*k); + coding = (char **)malloc(sizeof(char *)*m); + if (buffersize != origsize) { + for (i = 0; i < k; i++) { + data[i] = (char *)malloc(sizeof(char)*(buffersize/k)); + } + for (i = 0; i < m; i++) { + coding[i] = (char *)malloc(sizeof(char)*(buffersize/k)); + } + blocksize = buffersize/k; + } + + sprintf(temp, "%d", k); + md = strlen(temp); + timing_set(&t3); + + /* Create coding matrix or bitmatrix */ + switch(tech) { + case No_Coding: + break; + case Reed_Sol_Van: + matrix = reed_sol_vandermonde_coding_matrix(k, m, w); + break; + case Reed_Sol_R6_Op: + matrix = reed_sol_r6_coding_matrix(k, w); + break; + case Cauchy_Orig: + matrix = cauchy_original_coding_matrix(k, m, w); + bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix); + break; + case Cauchy_Good: + matrix = cauchy_good_general_coding_matrix(k, m, w); + bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix); + break; + case Liberation: + bitmatrix = liberation_coding_bitmatrix(k, w); + break; + case Blaum_Roth: + bitmatrix = blaum_roth_coding_bitmatrix(k, w); + break; + case Liber8tion: + bitmatrix = liber8tion_coding_bitmatrix(k); + } + timing_set(&t4); + totalsec += timing_delta(&t3, &t4); + + /* Begin decoding process */ + total = 0; + n = 1; + while (n <= readins) { + numerased = 0; + /* Open files, check for erasures, read in data/coding */ + for (i = 1; i <= k; i++) { + sprintf(fname, "%s/Coding/%s_k%0*d%s", curdir, cs1, md, i, extension); + fp = fopen(fname, "rb"); + if (fp == NULL) { + erased[i-1] = 1; + erasures[numerased] = i-1; + numerased++; + //printf("%s failed\n", fname); + } + else { + if (buffersize == origsize) { + stat(fname, &status); + blocksize = status.st_size; + data[i-1] = (char *)malloc(sizeof(char)*blocksize); + assert(blocksize == fread(data[i-1], sizeof(char), blocksize, fp)); + } + else { + fseek(fp, blocksize*(n-1), SEEK_SET); + assert(buffersize/k == fread(data[i-1], sizeof(char), buffersize/k, fp)); + } + fclose(fp); + } + } + for (i = 1; i <= m; i++) { + sprintf(fname, "%s/Coding/%s_m%0*d%s", curdir, cs1, md, i, extension); + fp = fopen(fname, "rb"); + if (fp == NULL) { + erased[k+(i-1)] = 1; + erasures[numerased] = k+i-1; + numerased++; + //printf("%s failed\n", fname); + } + else { + if (buffersize == origsize) { + stat(fname, &status); + blocksize = status.st_size; + coding[i-1] = (char *)malloc(sizeof(char)*blocksize); + assert(blocksize == fread(coding[i-1], sizeof(char), blocksize, fp)); + } + else { + fseek(fp, blocksize*(n-1), SEEK_SET); + assert(blocksize == fread(coding[i-1], sizeof(char), blocksize, fp)); + } + fclose(fp); + } + } + /* Finish allocating data/coding if needed */ + if (n == 1) { + for (i = 0; i < numerased; i++) { + if (erasures[i] < k) { + data[erasures[i]] = (char *)malloc(sizeof(char)*blocksize); + } + else { + coding[erasures[i]-k] = (char *)malloc(sizeof(char)*blocksize); + } + } + } + + erasures[numerased] = -1; + timing_set(&t3); + + /* Choose proper decoding method */ + if (tech == Reed_Sol_Van || tech == Reed_Sol_R6_Op) { + i = jerasure_matrix_decode(k, m, w, matrix, 1, erasures, data, coding, blocksize); + } + else if (tech == Cauchy_Orig || tech == Cauchy_Good || tech == Liberation || tech == Blaum_Roth || tech == Liber8tion) { + i = jerasure_schedule_decode_lazy(k, m, w, bitmatrix, erasures, data, coding, blocksize, packetsize, 1); + } + else { + fprintf(stderr, "Not a valid coding technique.\n"); + exit(0); + } + timing_set(&t4); + + /* Exit if decoding was unsuccessful */ + if (i == -1) { + fprintf(stderr, "Unsuccessful!\n"); + exit(0); + } + + /* Create decoded file */ + sprintf(fname, "%s/Coding/%s_decoded%s", curdir, cs1, extension); + if (n == 1) { + fp = fopen(fname, "wb"); + } + else { + fp = fopen(fname, "ab"); + } + for (i = 0; i < k; i++) { + if (total+blocksize <= origsize) { + fwrite(data[i], sizeof(char), blocksize, fp); + total+= blocksize; + } + else { + for (j = 0; j < blocksize; j++) { + if (total < origsize) { + fprintf(fp, "%c", data[i][j]); + total++; + } + else { + break; + } + + } + } + } + n++; + fclose(fp); + totalsec += timing_delta(&t3, &t4); + } + + /* Free allocated memory */ + free(cs1); + free(extension); + free(fname); + free(data); + free(coding); + free(erasures); + free(erased); + + /* Stop timing and print time */ + timing_set(&t2); + tsec = timing_delta(&t1, &t2); + printf("Decoding (MB/sec): %0.10f\n", (((double) origsize)/1024.0/1024.0)/totalsec); + printf("De_Total (MB/sec): %0.10f\n\n", (((double) origsize)/1024.0/1024.0)/tsec); + + return 0; +} + +void ctrl_bs_handler(int dummy) { + time_t mytime; + mytime = time(0); + fprintf(stderr, "\n%s\n", ctime(&mytime)); + fprintf(stderr, "You just typed ctrl-\\ in decoder.c\n"); + fprintf(stderr, "Total number of read ins = %d\n", readins); + fprintf(stderr, "Current read in: %d\n", n); + fprintf(stderr, "Method: %s\n\n", Methods[method]); + signal(SIGQUIT, ctrl_bs_handler); +} diff --git a/Examples/encode_decode.sh b/Examples/encode_decode.sh new file mode 100755 index 0000000..7f2fded --- /dev/null +++ b/Examples/encode_decode.sh @@ -0,0 +1,21 @@ +#!/bin/bash -e +# +# Copyright (C) 2014 Red Hat +# +# Author: Loic Dachary +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library 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 Library Public License for more details. +# +trap "rm -fr T Coding" EXIT + +dd if=/dev/urandom of=T bs=4096 count=1 +./encoder T 3 2 reed_sol_van 8 0 0 +./decoder T diff --git a/Examples/encoder.c b/Examples/encoder.c new file mode 100644 index 0000000..367686e --- /dev/null +++ b/Examples/encoder.c @@ -0,0 +1,627 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan. + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank. + */ + +/* + +This program takes as input an inputfile, k, m, a coding +technique, w, and packetsize. It creates k+m files from +the original file so that k of these files are parts of +the original file and m of the files are encoded based on +the given coding technique. The format of the created files +is the file name with "_k#" or "_m#" and then the extension. +(For example, inputfile test.txt would yield file "test_k1.txt".) +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jerasure.h" +#include "reed_sol.h" +#include "cauchy.h" +#include "liberation.h" +#include "timing.h" + +#define N 10 + +enum Coding_Technique {Reed_Sol_Van, Reed_Sol_R6_Op, Cauchy_Orig, Cauchy_Good, Liberation, Blaum_Roth, Liber8tion, RDP, EVENODD, No_Coding}; + +char *Methods[N] = {"reed_sol_van", "reed_sol_r6_op", "cauchy_orig", "cauchy_good", "liberation", "blaum_roth", "liber8tion", "no_coding"}; + +/* Global variables for signal handler */ +int readins, n; +enum Coding_Technique method; + +/* Function prototypes */ +int is_prime(int w); +void ctrl_bs_handler(int dummy); + +int jfread(void *ptr, int size, int nmembers, FILE *stream) +{ + if (stream != NULL) return fread(ptr, size, nmembers, stream); + + MOA_Fill_Random_Region(ptr, size); + return size; +} + + +int main (int argc, char **argv) { + FILE *fp, *fp2; // file pointers + char *block; // padding file + int size, newsize; // size of file and temp size + struct stat status; // finding file size + + + enum Coding_Technique tech; // coding technique (parameter) + int k, m, w, packetsize; // parameters + int buffersize; // paramter + int i; // loop control variables + int blocksize; // size of k+m files + int total; + int extra; + + /* Jerasure Arguments */ + char **data; + char **coding; + int *matrix; + int *bitmatrix; + int **schedule; + + /* Creation of file name variables */ + char temp[5]; + char *s1, *s2, *extension; + char *fname; + int md; + char *curdir; + + /* Timing variables */ + struct timing t1, t2, t3, t4; + double tsec; + double totalsec; + struct timing start; + + /* Find buffersize */ + int up, down; + + + signal(SIGQUIT, ctrl_bs_handler); + + /* Start timing */ + timing_set(&t1); + totalsec = 0.0; + matrix = NULL; + bitmatrix = NULL; + schedule = NULL; + + /* Error check Arguments*/ + if (argc != 8) { + fprintf(stderr, "usage: inputfile k m coding_technique w packetsize buffersize\n"); + fprintf(stderr, "\nChoose one of the following coding techniques: \nreed_sol_van, \nreed_sol_r6_op, \ncauchy_orig, \ncauchy_good, \nliberation, \nblaum_roth, \nliber8tion"); + fprintf(stderr, "\n\nPacketsize is ignored for the reed_sol's"); + fprintf(stderr, "\nBuffersize of 0 means the buffersize is chosen automatically.\n"); + fprintf(stderr, "\nIf you just want to test speed, use an inputfile of \"-number\" where number is the size of the fake file you want to test.\n\n"); + exit(0); + } + /* Conversion of parameters and error checking */ + if (sscanf(argv[2], "%d", &k) == 0 || k <= 0) { + fprintf(stderr, "Invalid value for k\n"); + exit(0); + } + if (sscanf(argv[3], "%d", &m) == 0 || m < 0) { + fprintf(stderr, "Invalid value for m\n"); + exit(0); + } + if (sscanf(argv[5],"%d", &w) == 0 || w <= 0) { + fprintf(stderr, "Invalid value for w.\n"); + exit(0); + } + if (argc == 6) { + packetsize = 0; + } + else { + if (sscanf(argv[6], "%d", &packetsize) == 0 || packetsize < 0) { + fprintf(stderr, "Invalid value for packetsize.\n"); + exit(0); + } + } + if (argc != 8) { + buffersize = 0; + } + else { + if (sscanf(argv[7], "%d", &buffersize) == 0 || buffersize < 0) { + fprintf(stderr, "Invalid value for buffersize\n"); + exit(0); + } + + } + + /* Determine proper buffersize by finding the closest valid buffersize to the input value */ + if (buffersize != 0) { + if (packetsize != 0 && buffersize%(sizeof(long)*w*k*packetsize) != 0) { + up = buffersize; + down = buffersize; + while (up%(sizeof(long)*w*k*packetsize) != 0 && (down%(sizeof(long)*w*k*packetsize) != 0)) { + up++; + if (down == 0) { + down--; + } + } + if (up%(sizeof(long)*w*k*packetsize) == 0) { + buffersize = up; + } + else { + if (down != 0) { + buffersize = down; + } + } + } + else if (packetsize == 0 && buffersize%(sizeof(long)*w*k) != 0) { + up = buffersize; + down = buffersize; + while (up%(sizeof(long)*w*k) != 0 && down%(sizeof(long)*w*k) != 0) { + up++; + down--; + } + if (up%(sizeof(long)*w*k) == 0) { + buffersize = up; + } + else { + buffersize = down; + } + } + } + + /* Setting of coding technique and error checking */ + + if (strcmp(argv[4], "no_coding") == 0) { + tech = No_Coding; + } + else if (strcmp(argv[4], "reed_sol_van") == 0) { + tech = Reed_Sol_Van; + if (w != 8 && w != 16 && w != 32) { + fprintf(stderr, "w must be one of {8, 16, 32}\n"); + exit(0); + } + } + else if (strcmp(argv[4], "reed_sol_r6_op") == 0) { + if (m != 2) { + fprintf(stderr, "m must be equal to 2\n"); + exit(0); + } + if (w != 8 && w != 16 && w != 32) { + fprintf(stderr, "w must be one of {8, 16, 32}\n"); + exit(0); + } + tech = Reed_Sol_R6_Op; + } + else if (strcmp(argv[4], "cauchy_orig") == 0) { + tech = Cauchy_Orig; + if (packetsize == 0) { + fprintf(stderr, "Must include packetsize.\n"); + exit(0); + } + } + else if (strcmp(argv[4], "cauchy_good") == 0) { + tech = Cauchy_Good; + if (packetsize == 0) { + fprintf(stderr, "Must include packetsize.\n"); + exit(0); + } + } + else if (strcmp(argv[4], "liberation") == 0) { + if (k > w) { + fprintf(stderr, "k must be less than or equal to w\n"); + exit(0); + } + if (w <= 2 || !(w%2) || !is_prime(w)) { + fprintf(stderr, "w must be greater than two and w must be prime\n"); + exit(0); + } + if (packetsize == 0) { + fprintf(stderr, "Must include packetsize.\n"); + exit(0); + } + if ((packetsize%(sizeof(long))) != 0) { + fprintf(stderr, "packetsize must be a multiple of sizeof(long)\n"); + exit(0); + } + tech = Liberation; + } + else if (strcmp(argv[4], "blaum_roth") == 0) { + if (k > w) { + fprintf(stderr, "k must be less than or equal to w\n"); + exit(0); + } + if (w <= 2 || !((w+1)%2) || !is_prime(w+1)) { + fprintf(stderr, "w must be greater than two and w+1 must be prime\n"); + exit(0); + } + if (packetsize == 0) { + fprintf(stderr, "Must include packetsize.\n"); + exit(0); + } + if ((packetsize%(sizeof(long))) != 0) { + fprintf(stderr, "packetsize must be a multiple of sizeof(long)\n"); + exit(0); + } + tech = Blaum_Roth; + } + else if (strcmp(argv[4], "liber8tion") == 0) { + if (packetsize == 0) { + fprintf(stderr, "Must include packetsize\n"); + exit(0); + } + if (w != 8) { + fprintf(stderr, "w must equal 8\n"); + exit(0); + } + if (m != 2) { + fprintf(stderr, "m must equal 2\n"); + exit(0); + } + if (k > w) { + fprintf(stderr, "k must be less than or equal to w\n"); + exit(0); + } + tech = Liber8tion; + } + else { + fprintf(stderr, "Not a valid coding technique. Choose one of the following: reed_sol_van, reed_sol_r6_op, cauchy_orig, cauchy_good, liberation, blaum_roth, liber8tion, no_coding\n"); + exit(0); + } + + /* Set global variable method for signal handler */ + method = tech; + + /* Get current working directory for construction of file names */ + curdir = (char*)malloc(sizeof(char)*1000); + assert(curdir == getcwd(curdir, 1000)); + + if (argv[1][0] != '-') { + + /* Open file and error check */ + fp = fopen(argv[1], "rb"); + if (fp == NULL) { + fprintf(stderr, "Unable to open file.\n"); + exit(0); + } + + /* Create Coding directory */ + i = mkdir("Coding", S_IRWXU); + if (i == -1 && errno != EEXIST) { + fprintf(stderr, "Unable to create Coding directory.\n"); + exit(0); + } + + /* Determine original size of file */ + stat(argv[1], &status); + size = status.st_size; + } else { + if (sscanf(argv[1]+1, "%d", &size) != 1 || size <= 0) { + fprintf(stderr, "Files starting with '-' should be sizes for randomly created input\n"); + exit(1); + } + fp = NULL; + MOA_Seed(time(0)); + } + + newsize = size; + + /* Find new size by determining next closest multiple */ + if (packetsize != 0) { + if (size%(k*w*packetsize*sizeof(long)) != 0) { + while (newsize%(k*w*packetsize*sizeof(long)) != 0) + newsize++; + } + } + else { + if (size%(k*w*sizeof(long)) != 0) { + while (newsize%(k*w*sizeof(long)) != 0) + newsize++; + } + } + + if (buffersize != 0) { + while (newsize%buffersize != 0) { + newsize++; + } + } + + + /* Determine size of k+m files */ + blocksize = newsize/k; + + /* Allow for buffersize and determine number of read-ins */ + if (size > buffersize && buffersize != 0) { + if (newsize%buffersize != 0) { + readins = newsize/buffersize; + } + else { + readins = newsize/buffersize; + } + block = (char *)malloc(sizeof(char)*buffersize); + blocksize = buffersize/k; + } + else { + readins = 1; + buffersize = size; + block = (char *)malloc(sizeof(char)*newsize); + } + + /* Break inputfile name into the filename and extension */ + s1 = (char*)malloc(sizeof(char)*(strlen(argv[1])+20)); + s2 = strrchr(argv[1], '/'); + if (s2 != NULL) { + s2++; + strcpy(s1, s2); + } + else { + strcpy(s1, argv[1]); + } + s2 = strchr(s1, '.'); + if (s2 != NULL) { + extension = strdup(s2); + *s2 = '\0'; + } else { + extension = strdup(""); + } + + /* Allocate for full file name */ + fname = (char*)malloc(sizeof(char)*(strlen(argv[1])+strlen(curdir)+20)); + sprintf(temp, "%d", k); + md = strlen(temp); + + /* Allocate data and coding */ + data = (char **)malloc(sizeof(char*)*k); + coding = (char **)malloc(sizeof(char*)*m); + for (i = 0; i < m; i++) { + coding[i] = (char *)malloc(sizeof(char)*blocksize); + if (coding[i] == NULL) { perror("malloc"); exit(1); } + } + + + + /* Create coding matrix or bitmatrix and schedule */ + timing_set(&t3); + switch(tech) { + case No_Coding: + break; + case Reed_Sol_Van: + matrix = reed_sol_vandermonde_coding_matrix(k, m, w); + break; + case Reed_Sol_R6_Op: + break; + case Cauchy_Orig: + matrix = cauchy_original_coding_matrix(k, m, w); + bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix); + schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix); + break; + case Cauchy_Good: + matrix = cauchy_good_general_coding_matrix(k, m, w); + bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix); + schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix); + break; + case Liberation: + bitmatrix = liberation_coding_bitmatrix(k, w); + schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix); + break; + case Blaum_Roth: + bitmatrix = blaum_roth_coding_bitmatrix(k, w); + schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix); + break; + case Liber8tion: + bitmatrix = liber8tion_coding_bitmatrix(k); + schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix); + break; + case RDP: + case EVENODD: + assert(0); + } + timing_set(&start); + timing_set(&t4); + totalsec += timing_delta(&t3, &t4); + + + + /* Read in data until finished */ + n = 1; + total = 0; + + while (n <= readins) { + /* Check if padding is needed, if so, add appropriate + number of zeros */ + if (total < size && total+buffersize <= size) { + total += jfread(block, sizeof(char), buffersize, fp); + } + else if (total < size && total+buffersize > size) { + extra = jfread(block, sizeof(char), buffersize, fp); + for (i = extra; i < buffersize; i++) { + block[i] = '0'; + } + } + else if (total == size) { + for (i = 0; i < buffersize; i++) { + block[i] = '0'; + } + } + + /* Set pointers to point to file data */ + for (i = 0; i < k; i++) { + data[i] = block+(i*blocksize); + } + + timing_set(&t3); + /* Encode according to coding method */ + switch(tech) { + case No_Coding: + break; + case Reed_Sol_Van: + jerasure_matrix_encode(k, m, w, matrix, data, coding, blocksize); + break; + case Reed_Sol_R6_Op: + reed_sol_r6_encode(k, w, data, coding, blocksize); + break; + case Cauchy_Orig: + jerasure_schedule_encode(k, m, w, schedule, data, coding, blocksize, packetsize); + break; + case Cauchy_Good: + jerasure_schedule_encode(k, m, w, schedule, data, coding, blocksize, packetsize); + break; + case Liberation: + jerasure_schedule_encode(k, m, w, schedule, data, coding, blocksize, packetsize); + break; + case Blaum_Roth: + jerasure_schedule_encode(k, m, w, schedule, data, coding, blocksize, packetsize); + break; + case Liber8tion: + jerasure_schedule_encode(k, m, w, schedule, data, coding, blocksize, packetsize); + break; + case RDP: + case EVENODD: + assert(0); + } + timing_set(&t4); + + /* Write data and encoded data to k+m files */ + for (i = 1; i <= k; i++) { + if (fp == NULL) { + bzero(data[i-1], blocksize); + } else { + sprintf(fname, "%s/Coding/%s_k%0*d%s", curdir, s1, md, i, extension); + if (n == 1) { + fp2 = fopen(fname, "wb"); + } + else { + fp2 = fopen(fname, "ab"); + } + fwrite(data[i-1], sizeof(char), blocksize, fp2); + fclose(fp2); + } + + } + for (i = 1; i <= m; i++) { + if (fp == NULL) { + bzero(data[i-1], blocksize); + } else { + sprintf(fname, "%s/Coding/%s_m%0*d%s", curdir, s1, md, i, extension); + if (n == 1) { + fp2 = fopen(fname, "wb"); + } + else { + fp2 = fopen(fname, "ab"); + } + fwrite(coding[i-1], sizeof(char), blocksize, fp2); + fclose(fp2); + } + } + n++; + /* Calculate encoding time */ + totalsec += timing_delta(&t3, &t4); + } + + /* Create metadata file */ + if (fp != NULL) { + sprintf(fname, "%s/Coding/%s_meta.txt", curdir, s1); + fp2 = fopen(fname, "wb"); + fprintf(fp2, "%s\n", argv[1]); + fprintf(fp2, "%d\n", size); + fprintf(fp2, "%d %d %d %d %d\n", k, m, w, packetsize, buffersize); + fprintf(fp2, "%s\n", argv[4]); + fprintf(fp2, "%d\n", tech); + fprintf(fp2, "%d\n", readins); + fclose(fp2); + } + + + /* Free allocated memory */ + free(s1); + free(fname); + free(block); + free(curdir); + + /* Calculate rate in MB/sec and print */ + timing_set(&t2); + tsec = timing_delta(&t1, &t2); + printf("Encoding (MB/sec): %0.10f\n", (((double) size)/1024.0/1024.0)/totalsec); + printf("En_Total (MB/sec): %0.10f\n", (((double) size)/1024.0/1024.0)/tsec); + + return 0; +} + +/* is_prime returns 1 if number if prime, 0 if not prime */ +int is_prime(int w) { + int prime55[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71, + 73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179, + 181,191,193,197,199,211,223,227,229,233,239,241,251,257}; + int i; + for (i = 0; i < 55; i++) { + if (w%prime55[i] == 0) { + if (w == prime55[i]) return 1; + else { return 0; } + } + } + assert(0); +} + +/* Handles ctrl-\ event */ +void ctrl_bs_handler(int dummy) { + time_t mytime; + mytime = time(0); + fprintf(stderr, "\n%s\n", ctime(&mytime)); + fprintf(stderr, "You just typed ctrl-\\ in encoder.c.\n"); + fprintf(stderr, "Total number of read ins = %d\n", readins); + fprintf(stderr, "Current read in: %d\n", n); + fprintf(stderr, "Method: %s\n\n", Methods[method]); + signal(SIGQUIT, ctrl_bs_handler); +} diff --git a/Examples/jerasure_01.c b/Examples/jerasure_01.c new file mode 100644 index 0000000..20df225 --- /dev/null +++ b/Examples/jerasure_01.c @@ -0,0 +1,92 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan. + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank. + */ + +#include +#include +#include "jerasure.h" + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +static void usage(char *s) +{ + fprintf(stderr, "usage: jerasure_01 r c w - creates and prints out a matrix in GF(2^w).\n\n"); + fprintf(stderr, " Element i,j is equal to 2^(i*c+j)\n"); + fprintf(stderr, " \n"); + fprintf(stderr, "This demonstrates jerasure_print_matrix().\n"); + if (s != NULL) fprintf(stderr, "%s\n", s); + exit(1); +} + +int main(int argc, char **argv) +{ + int r, c, w, i, n; + int *matrix; + + if (argc != 4) usage(NULL); + if (sscanf(argv[1], "%d", &r) == 0 || r <= 0) usage("Bad r"); + if (sscanf(argv[2], "%d", &c) == 0 || c <= 0) usage("Bad c"); + if (sscanf(argv[3], "%d", &w) == 0 || w <= 0) usage("Bad w"); + + matrix = talloc(int, r*c); + + n = 1; + for (i = 0; i < r*c; i++) { + matrix[i] = n; + n = galois_single_multiply(n, 2, w); + } + + printf("jerasure_01"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("\n"); + printf("

jerasure_01"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("

\n"); + printf("
\n");
+
+  jerasure_print_matrix(matrix, r, c, w);
+  return 0;
+}
+
diff --git a/Examples/jerasure_02.c b/Examples/jerasure_02.c
new file mode 100644
index 0000000..eb952ae
--- /dev/null
+++ b/Examples/jerasure_02.c
@@ -0,0 +1,94 @@
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Jerasure's authors:
+
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan.
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank.
+ */
+
+#include 
+#include 
+#include "jerasure.h"
+
+#define talloc(type, num) (type *) malloc(sizeof(type)*(num))
+
+static void usage(char *s)
+{
+  fprintf(stderr, "usage: jerasure_02 r c w - Converts the matrix of jerasure_01 to a bit matrix.\n");
+  fprintf(stderr, "       \n");
+  fprintf(stderr, "This demonstrates jerasure_print_bitmatrix() and jerasure_matrix_to_bitmatrix().\n");
+  if (s != NULL) fprintf(stderr, "%s\n", s);
+  exit(1);
+}
+
+int main(int argc, char **argv)
+{
+  int r, c, w, i, n;
+  int *matrix;
+  int *bitmatrix;
+
+  if (argc != 4) usage(NULL);
+  if (sscanf(argv[1], "%d", &r) == 0 || r <= 0) usage("Bad r");
+  if (sscanf(argv[2], "%d", &c) == 0 || c <= 0) usage("Bad c");
+  if (sscanf(argv[3], "%d", &w) == 0 || w <= 0) usage("Bad w");
+
+  matrix = talloc(int, r*c);
+
+  n = 1;
+  for (i = 0; i < r*c; i++) {
+    matrix[i] = n;
+    n = galois_single_multiply(n, 2, w);
+  }
+
+  bitmatrix = jerasure_matrix_to_bitmatrix(c, r, w, matrix);
+
+  printf("jerasure_02");
+  for (i = 1; i < argc; i++) printf(" %s", argv[i]);
+  printf("\n");
+  printf("

jerasure_02"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("

\n"); + printf("
\n");
+
+  jerasure_print_bitmatrix(bitmatrix, r*w, c*w, w);
+  return 0;
+}
+
diff --git a/Examples/jerasure_03.c b/Examples/jerasure_03.c
new file mode 100644
index 0000000..24bd15c
--- /dev/null
+++ b/Examples/jerasure_03.c
@@ -0,0 +1,119 @@
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Jerasure's authors:
+
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan.
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank.
+ */
+
+#include 
+#include 
+#include 
+#include "jerasure.h"
+
+#define talloc(type, num) (type *) malloc(sizeof(type)*(num))
+
+static void usage(char *s)
+{
+  fprintf(stderr, "usage: jerasure_03 k w - Creates a kxk Cauchy matrix in GF(2^w). \n\n");
+  fprintf(stderr, "       k must be < 2^w.  Element i,j is 1/(i+(2^w-j-1)).  (If that is\n");
+  fprintf(stderr, "       If that is 1/0, then it sets it to zero).  \n");
+  fprintf(stderr, "       It then tests whether that matrix is invertible.\n");
+  fprintf(stderr, "       If it is invertible, then it prints out the inverse.\n");
+  fprintf(stderr, "       Finally, it prints the product of the matrix and its inverse.\n");
+  fprintf(stderr, "       \n");
+  fprintf(stderr, "This demonstrates: jerasure_print_matrix()\n");
+  fprintf(stderr, "                   jerasure_invertible_matrix()\n");
+  fprintf(stderr, "                   jerasure_invert_matrix()\n");
+  fprintf(stderr, "                   jerasure_matrix_multiply().\n");
+  if (s != NULL) fprintf(stderr, "%s\n", s);
+  exit(1);
+}
+
+int main(int argc, char **argv)
+{
+  unsigned int k, w, i, j, n;
+  int *matrix;
+  int *matrix_copy;
+  int *inverse;
+  int *identity;
+
+  if (argc != 3) usage(NULL);
+  if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k");
+  if (sscanf(argv[2], "%d", &w) == 0 || w <= 0 || w > 31) usage("Bad w");
+  if (k >= (1 << w)) usage("K too big");
+
+  matrix = talloc(int, k*k);
+  matrix_copy = talloc(int, k*k);
+  inverse = talloc(int, k*k);
+
+  for (i = 0; i < k; i++) {
+    for (j = 0; j < k; j++) {
+      n = i ^ ((1 << w)-1-j);
+      matrix[i*k+j] = (n == 0) ? 0 : galois_single_divide(1, n, w);
+    }
+  }
+
+  printf("jerasure_03");
+  for (i = 1; i < argc; i++) printf(" %s", argv[i]);
+  printf("\n");
+  printf("

jerasure_03"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("

\n"); + printf("
\n");
+
+  printf("The Cauchy Matrix:\n");
+  jerasure_print_matrix(matrix, k, k, w);
+  memcpy(matrix_copy, matrix, sizeof(int)*k*k);
+  i = jerasure_invertible_matrix(matrix_copy, k, w);
+  printf("\nInvertible: %s\n", (i == 1) ? "Yes" : "No");
+  if (i == 1) {
+    printf("\nInverse:\n");
+    memcpy(matrix_copy, matrix, sizeof(int)*k*k);
+    i = jerasure_invert_matrix(matrix_copy, inverse, k, w);
+    jerasure_print_matrix(inverse, k, k, w);
+    identity = jerasure_matrix_multiply(inverse, matrix, k, k, k, k, w);
+    printf("\nInverse times matrix (should be identity):\n");
+    jerasure_print_matrix(identity, k, k, w);
+  }
+  return 0;
+}
+
diff --git a/Examples/jerasure_04.c b/Examples/jerasure_04.c
new file mode 100644
index 0000000..21410a5
--- /dev/null
+++ b/Examples/jerasure_04.c
@@ -0,0 +1,118 @@
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Jerasure's authors:
+
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan.
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank.
+ */
+
+#include 
+#include 
+#include 
+#include "jerasure.h"
+
+#define talloc(type, num) (type *) malloc(sizeof(type)*(num))
+
+static void usage(char *s)
+{
+  fprintf(stderr, "usage: jerasure_04 k w - Performs the analogous bit-matrix operations to jerasure_03.\n\n");
+  fprintf(stderr, "       It converts the matrix to a kw*kw bit matrix and does the same operations.\n");
+  fprintf(stderr, "       k must be < 2^w.\n");
+  fprintf(stderr, "This demonstrates: jerasure_print_bitmatrix()\n");
+  fprintf(stderr, "                   jerasure_matrix_to_bitmatrix()\n");
+  fprintf(stderr, "                   jerasure_invertible_bitmatrix()\n");
+  fprintf(stderr, "                   jerasure_invert_bitmatrix()\n");
+  fprintf(stderr, "                   jerasure_matrix_multiply().\n");
+  if (s != NULL) fprintf(stderr, "%s\n", s);
+  exit(1);
+}
+
+int main(int argc, char **argv)
+{
+  unsigned int k, w, i, j, n;
+  int *matrix;
+  int *bitmatrix;
+  int *bitmatrix_copy;
+  int *inverse;
+  int *identity;
+
+  if (argc != 3) usage(NULL);
+  if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k");
+  if (sscanf(argv[2], "%d", &w) == 0 || w <= 0 || w > 31) usage("Bad w");
+  if (k >= (1 << w)) usage("K too big");
+
+  matrix = talloc(int, k*k);
+  bitmatrix_copy = talloc(int, k*w*k*w);
+  inverse = talloc(int, k*w*k*w);
+
+  for (i = 0; i < k; i++) {
+    for (j = 0; j < k; j++) {
+      n = i ^ ((1 << w)-1-j);
+      matrix[i*k+j] = (n == 0) ? 0 : galois_single_divide(1, n, w);
+    }
+  }
+  bitmatrix = jerasure_matrix_to_bitmatrix(k, k, w, matrix);
+
+  printf("jerasure_04");
+  for (i = 1; i < argc; i++) printf(" %s", argv[i]);
+  printf("\n");
+  printf("

jerasure_04"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("

\n"); + printf("
\n");
+
+  printf("The Cauchy Bit-Matrix:\n");
+  jerasure_print_bitmatrix(bitmatrix, k*w, k*w, w);
+  memcpy(bitmatrix_copy, bitmatrix, sizeof(int)*k*w*k*w);
+  i = jerasure_invertible_bitmatrix(bitmatrix_copy, k*w);
+  printf("\nInvertible: %s\n", (i == 1) ? "Yes" : "No");
+  if (i == 1) {
+    printf("\nInverse:\n");
+    memcpy(bitmatrix_copy, bitmatrix, sizeof(int)*k*w*k*w);
+    i = jerasure_invert_bitmatrix(bitmatrix_copy, inverse, k*w);
+    jerasure_print_bitmatrix(inverse, k*w, k*w, w);
+    identity = jerasure_matrix_multiply(inverse, bitmatrix, k*w, k*w, k*w, k*w, 2);
+    printf("\nInverse times matrix (should be identity):\n");
+    jerasure_print_bitmatrix(identity, k*w, k*w, w);
+  }
+  return 0;
+}
+
diff --git a/Examples/jerasure_05.c b/Examples/jerasure_05.c
new file mode 100644
index 0000000..20b059b
--- /dev/null
+++ b/Examples/jerasure_05.c
@@ -0,0 +1,217 @@
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Jerasure's authors:
+
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan.
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "jerasure.h"
+
+#define talloc(type, num) (type *) malloc(sizeof(type)*(num))
+
+static void usage(char *s)
+{
+  fprintf(stderr, "usage: jerasure_05 k m w size seed - Does a simple Reed-Solomon coding example in GF(2^w).\n");
+  fprintf(stderr, "       \n");
+  fprintf(stderr, "       k+m must be <= 2^w.  w can be 8, 16 or 32.\n");
+  fprintf(stderr, "       It sets up a Cauchy generator matrix and encodes\n");
+  fprintf(stderr, "       k devices of size bytes with it.  Then it decodes.\n");
+  fprintf(stderr, "       After that, it decodes device 0 by using jerasure_make_decoding_matrix()\n");
+  fprintf(stderr, "       and jerasure_matrix_dotprod().\n");
+  fprintf(stderr, "       \n");
+  fprintf(stderr, "This demonstrates: jerasure_matrix_encode()\n");
+  fprintf(stderr, "                   jerasure_matrix_decode()\n");
+  fprintf(stderr, "                   jerasure_print_matrix()\n");
+  fprintf(stderr, "                   jerasure_make_decoding_matrix()\n");
+  fprintf(stderr, "                   jerasure_matrix_dotprod()\n");
+  if (s != NULL) fprintf(stderr, "\n%s\n\n", s);
+  exit(1);
+}
+
+static void print_data_and_coding(int k, int m, int w, int size, 
+		char **data, char **coding) 
+{
+  int i, j, x;
+  int n, sp;
+
+  if(k > m) n = k;
+  else n = m;
+  sp = size * 2 + size/(w/8) + 8;
+
+  printf("%-*sCoding\n", sp, "Data");
+  for(i = 0; i < n; i++) {
+	  if(i < k) {
+		  printf("D%-2d:", i);
+		  for(j=0;j< size; j+=(w/8)) { 
+			  printf(" ");
+			  for(x=0;x < w/8;x++){
+				printf("%02x", (unsigned char)data[i][j+x]);
+			  }
+		  }
+		  printf("    ");
+	  }
+	  else printf("%*s", sp, "");
+	  if(i < m) {
+		  printf("C%-2d:", i);
+		  for(j=0;j< size; j+=(w/8)) { 
+			  printf(" ");
+			  for(x=0;x < w/8;x++){
+				printf("%02x", (unsigned char)coding[i][j+x]);
+			  }
+		  }
+	  }
+	  printf("\n");
+  }
+	printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+  int k, m, w, size;
+  int i, j;
+  int *matrix;
+  char **data, **coding;
+  int *erasures, *erased;
+  int *decoding_matrix, *dm_ids;
+  uint32_t seed;
+  
+  if (argc != 6) usage(NULL);
+  if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k");
+  if (sscanf(argv[2], "%d", &m) == 0 || m <= 0) usage("Bad m");
+  if (sscanf(argv[3], "%d", &w) == 0 || (w != 8 && w != 16 && w != 32)) usage("Bad w");
+  if (w < 32 && k + m > (1 << w)) usage("k + m must be <= 2 ^ w");
+  if (sscanf(argv[4], "%d", &size) == 0 || size % sizeof(long) != 0) 
+		usage("size must be multiple of sizeof(long)");
+  if (sscanf(argv[5], "%d", &seed) == 0) usage("Bad seed");
+
+  matrix = talloc(int, m*k);
+  for (i = 0; i < m; i++) {
+    for (j = 0; j < k; j++) {
+      matrix[i*k+j] = galois_single_divide(1, i ^ (m + j), w);
+    }
+  }
+
+  printf("jerasure_05");
+  for (i = 1; i < argc; i++) printf(" %s", argv[i]);
+  printf("\n");
+  printf("

jerasure_05"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("

\n"); + printf("
\n");
+
+  printf("The Coding Matrix (the last m rows of the Generator Matrix G^T):\n\n");
+  jerasure_print_matrix(matrix, m, k, w);
+  printf("\n");
+
+  MOA_Seed(seed);
+  data = talloc(char *, k);
+  for (i = 0; i < k; i++) {
+    data[i] = talloc(char, size);
+    MOA_Fill_Random_Region(data[i], size);
+  }
+
+  coding = talloc(char *, m);
+  for (i = 0; i < m; i++) {
+    coding[i] = talloc(char, size);
+  }
+
+  jerasure_matrix_encode(k, m, w, matrix, data, coding, size);
+  
+  printf("Encoding Complete:\n\n");
+  print_data_and_coding(k, m, w, size, data, coding);
+
+  erasures = talloc(int, (m+1));
+  erased = talloc(int, (k+m));
+  for (i = 0; i < m+k; i++) erased[i] = 0;
+  for (i = 0; i < m; ) {
+    erasures[i] = (MOA_Random_W(w, 1))%(k+m);
+    if (erased[erasures[i]] == 0) {
+      erased[erasures[i]] = 1;
+	  
+      bzero((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], size);
+      i++;
+    }
+  }
+  erasures[i] = -1;
+
+  printf("Erased %d random devices:\n\n", m);
+  print_data_and_coding(k, m, w, size, data, coding);
+  
+  i = jerasure_matrix_decode(k, m, w, matrix, 0, erasures, data, coding, size);
+
+  printf("State of the system after decoding:\n\n");
+  print_data_and_coding(k, m, w, size, data, coding);
+  
+  decoding_matrix = talloc(int, k*k);
+  dm_ids = talloc(int, k);
+
+  for (i = 0; i < m; i++) erased[i] = 1;
+  for (; i < k+m; i++) erased[i] = 0;
+
+  jerasure_make_decoding_matrix(k, m, w, matrix, erased, decoding_matrix, dm_ids);
+
+  printf("Suppose we erase the first %d devices.  Here is the decoding matrix:\n\n", m);
+  jerasure_print_matrix(decoding_matrix, k, k, w);
+  printf("\n");
+  printf("And dm_ids:\n\n");
+  jerasure_print_matrix(dm_ids, 1, k, w);
+
+  bzero(data[0], size);
+  jerasure_matrix_dotprod(k, w, decoding_matrix, dm_ids, 0, data, coding, size);
+
+  printf("\nAfter calling jerasure_matrix_dotprod, we calculate the value of device #0 to be:\n\n");
+  printf("D0 :");
+  for(i=0;i< size; i+=(w/8)) {
+	  printf(" ");
+	  for(j=0;j < w/8;j++){
+		printf("%02x", (unsigned char)data[0][i+j]);
+	  }
+  }
+  printf("\n\n");
+
+  return 0;
+}
diff --git a/Examples/jerasure_06.c b/Examples/jerasure_06.c
new file mode 100644
index 0000000..9af9ca2
--- /dev/null
+++ b/Examples/jerasure_06.c
@@ -0,0 +1,233 @@
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Jerasure's authors:
+
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan.
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "jerasure.h"
+
+#define talloc(type, num) (type *) malloc(sizeof(type)*(num))
+
+static void usage(char *s)
+{
+  fprintf(stderr, "usage: jerasure_06 k m w packetsize seed\n");
+  fprintf(stderr, "Does a simple Cauchy Reed-Solomon coding example in GF(2^w).\n");
+  fprintf(stderr, "       \n");
+  fprintf(stderr, "       k+m must be < 2^w.  Packetsize must be a multiple of sizeof(long)\n");
+  fprintf(stderr, "       It sets up a Cauchy generator matrix and encodes k devices of w*packetsize bytes.\n");
+  fprintf(stderr, "       After that, it decodes device 0 by using jerasure_make_decoding_bitmatrix()\n");
+  fprintf(stderr, "       and jerasure_bitmatrix_dotprod().\n");
+  fprintf(stderr, "       \n");
+  fprintf(stderr, "This demonstrates: jerasure_bitmatrix_encode()\n");
+  fprintf(stderr, "                   jerasure_bitmatrix_decode()\n");
+  fprintf(stderr, "                   jerasure_print_bitmatrix()\n");
+  fprintf(stderr, "                   jerasure_make_decoding_bitmatrix()\n");
+  fprintf(stderr, "                   jerasure_bitmatrix_dotprod()\n");
+  if (s != NULL) fprintf(stderr, "\n%s\n\n", s);
+  exit(1);
+}
+
+static void print_array(char **ptrs, int ndevices, int size, int packetsize, char *label)
+{
+  int i, j, x;
+  unsigned char *up;
+
+  printf("
\n"); + + for (i = 0; i < ndevices; i++) printf("\n", label, i); + printf("\n"); + printf("\n"); + for (i = 0; i < ndevices; i++) { + printf("\n"); + } + printf("
%s%x
");
+  for (j = 0; j < size/packetsize; j++) printf("Packet %d\n", j);
+  printf("
");
+    up = (unsigned char *) ptrs[i];
+    for (j = 0; j < size/packetsize; j++) {
+      for (x = 0; x < packetsize; x++) {
+        if (x > 0 && x%4 == 0) printf(" ");
+        printf("%02x", up[j*packetsize+x]);
+      }
+      printf("\n");
+    }
+    printf("
\n"); +} + +int main(int argc, char **argv) +{ + int k, w, i, j, m, psize, x; + int *matrix, *bitmatrix; + char **data, **coding; + int *erasures, *erased; + int *decoding_matrix, *dm_ids; + uint32_t seed; + + if (argc != 6) usage(NULL); + if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k"); + if (sscanf(argv[2], "%d", &m) == 0 || m <= 0) usage("Bad m"); + if (sscanf(argv[3], "%d", &w) == 0 || w <= 0 || w > 32) usage("Bad w"); + if (w < 30 && (k+m) > (1 << w)) usage("k + m is too big"); + if (sscanf(argv[4], "%d", &psize) == 0 || psize <= 0) usage("Bad packetsize"); + if(psize%sizeof(long) != 0) usage("Packetsize must be multiple of sizeof(long)"); + if (sscanf(argv[5], "%d", &seed) == 0) usage("Bad seed"); + + MOA_Seed(seed); + matrix = talloc(int, m*k); + for (i = 0; i < m; i++) { + for (j = 0; j < k; j++) { + matrix[i*k+j] = galois_single_divide(1, i ^ (m + j), w); + } + } + bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix); + + printf("jerasure_06"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("\n"); + printf("

jerasure_06"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("

\n"); + + printf("
\n"); + printf("Last (m * w) rows of the Generator Matrix: (G^T):\n
\n");
+  jerasure_print_bitmatrix(bitmatrix, w*m, w*k, w);
+  printf("

\n"); + + data = talloc(char *, k); + for (i = 0; i < k; i++) { + data[i] = talloc(char, psize*w); + MOA_Fill_Random_Region(data[i], psize*w); + } + + coding = talloc(char *, m); + for (i = 0; i < m; i++) { + coding[i] = talloc(char, psize*w); + } + + jerasure_bitmatrix_encode(k, m, w, bitmatrix, data, coding, w*psize, psize); + + printf("Encoding Complete - Here is the state of the system\n\n"); + printf("

\n"); + print_array(data, k, psize*w, psize, "D"); + printf("

\n"); + print_array(coding, m, psize*w, psize, "C"); + printf("


\n"); + + erasures = talloc(int, (m+1)); + erased = talloc(int, (k+m)); + for (i = 0; i < m+k; i++) erased[i] = 0; + for (i = 0; i < m; ) { + erasures[i] = MOA_Random_W(w, 1)%(k+m); + if (erased[erasures[i]] == 0) { + erased[erasures[i]] = 1; + bzero((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], psize*w); + i++; + } + } + erasures[i] = -1; + + printf("Erased %d random devices:", m); + for (i = 0; erasures[i] != -1; i++) { + printf(" %c%x", ((erasures[i] < k) ? 'D' : 'C'), (erasures[i] < k ? erasures[i] : erasures[i]-k)); + } + printf(". Here is the state of the system:\n"); + + printf("

\n"); + print_array(data, k, psize*w, psize, "D"); + printf("

\n"); + print_array(coding, m, psize*w, psize, "C"); + printf("


\n"); + + i = jerasure_bitmatrix_decode(k, m, w, bitmatrix, 0, erasures, data, coding, + w*psize, psize); + + printf("Here is the state of the system after decoding:\n\n"); + printf("

\n"); + print_array(data, k, psize*w, psize, "D"); + printf("

\n"); + print_array(coding, m, psize*w, psize, "C"); + printf("


\n"); + + decoding_matrix = talloc(int, k*k*w*w); + dm_ids = talloc(int, k); + + x = (m < k) ? m : k; + + for (i = 0; i < x; i++) erased[i] = 1; + for (; i < k+m; i++) erased[i] = 0; + + jerasure_make_decoding_bitmatrix(k, m, w, bitmatrix, erased, decoding_matrix, dm_ids); + + printf("Suppose we erase the first %d devices. Here is the decoding matrix:\n
\n", x);
+  jerasure_print_bitmatrix(decoding_matrix, k*w, k*w, w);
+  printf("
\n"); + printf("And dm_ids:\n
\n");
+  jerasure_print_matrix(dm_ids, 1, k, w);
+  printf("

\n"); + + for (i = 0; i < x; i++) bzero(data[i], w*psize); + + printf("Here is the state of the system after the erasures:\n\n"); + printf("

\n"); + print_array(data, k, psize*w, psize, "D"); + printf("

\n"); + print_array(coding, m, psize*w, psize, "C"); + printf("


\n"); + + for (i = 0; i < x; i++) { + jerasure_bitmatrix_dotprod(k, w, decoding_matrix+i*(k*w*w), dm_ids, i, data, coding, w*psize, psize); + } + + printf("Here is the state of the system after calling jerasure_bitmatrix_dotprod() %d time%s with the decoding matrix:\n\n", x, (x == 1) ? "" : "s"); + printf("

\n"); + print_array(data, k, psize*w, psize, "D"); + printf("

\n"); + print_array(coding, m, psize*w, psize, "C"); + printf("


\n"); + return 0; +} diff --git a/Examples/jerasure_07.c b/Examples/jerasure_07.c new file mode 100644 index 0000000..cc57163 --- /dev/null +++ b/Examples/jerasure_07.c @@ -0,0 +1,223 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan. + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank. + */ + +#include +#include +#include +#include +#include +#include "jerasure.h" + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +static void usage(char *s) +{ + fprintf(stderr, "usage: jerasure_07 k m w seed - Scheduled Cauchy Reed-Solomon coding example in GF(2^w).\n"); + fprintf(stderr, " \n"); + fprintf(stderr, " k+m must be <= 2^w. It sets up a Cauchy generator matrix and encodes\n"); + fprintf(stderr, " k sets of w*%ld bytes. It uses bit-matrix scheduling, both smart and dumb.\n", sizeof(long)); + fprintf(stderr, " It decodes using bit-matrix scheduling, then shows an example of\n"); + fprintf(stderr, " using jerasure_do_scheduled_operations().\n"); + fprintf(stderr, " \n"); + fprintf(stderr, "This demonstrates: jerasure_dumb_bitmatrix_to_schedule()\n"); + fprintf(stderr, " jerasure_smart_bitmatrix_to_schedule()\n"); + fprintf(stderr, " jerasure_schedule_encode()\n"); + fprintf(stderr, " jerasure_schedule_decode_lazy()\n"); + fprintf(stderr, " jerasure_do_scheduled_operations()\n"); + fprintf(stderr, " jerasure_get_stats()\n"); + if (s != NULL) fprintf(stderr, "%s\n", s); + exit(1); +} + +static void print_array(char **ptrs, int ndevices, int size, int packetsize, char *label) +{ + int i, j, x; + unsigned char *up; + + printf("
\n"); + + for (i = 0; i < ndevices; i++) printf("\n", label, i); + printf("\n"); + printf("\n"); + for (i = 0; i < ndevices; i++) { + printf("\n"); + } + printf("
%s%x
");
+  for (j = 0; j < size/packetsize; j++) printf("Packet %d\n", j);
+  printf("
");
+    up = (unsigned char *) ptrs[i];
+    for (j = 0; j < size/packetsize; j++) {
+      for (x = 0; x < packetsize; x++) {
+        if (x > 0 && x%4 == 0) printf(" ");
+        printf("%02x", up[j*packetsize+x]);
+      }
+      printf("\n");
+    }
+    printf("
\n"); +} + +int main(int argc, char **argv) +{ + int k, w, i, j, m; + int *matrix, *bitmatrix; + char **data, **coding, **ptrs; + int **smart, **dumb; + int *erasures, *erased; + double stats[3]; + uint32_t seed; + + if (argc != 5) usage("Wrong number of arguments"); + if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k"); + if (sscanf(argv[2], "%d", &m) == 0 || m <= 0) usage("Bad m"); + if (sscanf(argv[3], "%d", &w) == 0 || w <= 0 || w > 32) usage("Bad w"); + if (sscanf(argv[4], "%d", &seed) == 0) usage("Bad seed"); + if (w < 30 && (k+m) > (1 << w)) usage("k + m is too big"); + + matrix = talloc(int, m*k); + for (i = 0; i < m; i++) { + for (j = 0; j < k; j++) { + matrix[i*k+j] = galois_single_divide(1, i ^ (m + j), w); + } + } + bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix); + + printf("jerasure_07"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("\n"); + printf("

jerasure_07"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("

\n"); + printf("
\n"); + + printf("Last m*w rows of the generator matrix (G^T):\n
\n");
+  jerasure_print_bitmatrix(bitmatrix, w*m, w*k, w);
+  printf("

\n"); + + dumb = jerasure_dumb_bitmatrix_to_schedule(k, m, w, bitmatrix); + smart = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix); + + MOA_Seed(seed); + data = talloc(char *, k); + for (i = 0; i < k; i++) { + data[i] = talloc(char, sizeof(long)*w); + MOA_Fill_Random_Region(data[i], sizeof(long)*w); + } + + coding = talloc(char *, m); + for (i = 0; i < m; i++) { + coding[i] = talloc(char, sizeof(long)*w); + } + + jerasure_schedule_encode(k, m, w, dumb, data, coding, w*sizeof(long), sizeof(long)); + jerasure_get_stats(stats); + printf("Dumb Encoding Complete: - %.0lf XOR'd bytes. State of the system:\n\n", stats[0]); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + jerasure_schedule_encode(k, m, w, smart, data, coding, w*sizeof(long), sizeof(long)); + jerasure_get_stats(stats); + printf("Smart Encoding Complete: - %.0lf XOR'd bytes\n\n", stats[0]); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + erasures = talloc(int, (m+1)); + erased = talloc(int, (k+m)); + for (i = 0; i < m+k; i++) erased[i] = 0; + for (i = 0; i < m; ) { + erasures[i] = MOA_Random_W(w, 1)%(k+m); + if (erased[erasures[i]] == 0) { + erased[erasures[i]] = 1; + bzero((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], sizeof(long)*w); + i++; + } + } + erasures[i] = -1; + + printf("Erased %d random devices:\n\n", m); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + jerasure_schedule_decode_lazy(k, m, w, bitmatrix, erasures, data, coding, w*sizeof(long), sizeof(long), 1); + jerasure_get_stats(stats); + + printf("State of the system after decoding: %.0lf XOR'd bytes\n\n", stats[0]); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + ptrs = talloc(char *, (k+m)); + for (i = 0; i < k; i++) ptrs[i] = data[i]; + for (i = 0; i < m; i++) ptrs[k+i] = coding[i]; + + for (j = 0; j < m; j++) bzero(coding[j], sizeof(long)*w); + printf("State of the system after erasing the coding devices:\n"); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + jerasure_do_scheduled_operations(ptrs, smart, sizeof(long)); + printf("And using jerasure_do_scheduled_operations(): %.0lf XOR'd bytes\n\n", stats[0]); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + return 0; +} diff --git a/Examples/jerasure_08.c b/Examples/jerasure_08.c new file mode 100644 index 0000000..0eb5ace --- /dev/null +++ b/Examples/jerasure_08.c @@ -0,0 +1,232 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan. + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank. + */ + +#include +#include +#include +#include +#include +#include "jerasure.h" + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +static void usage(char *s) +{ + fprintf(stderr, "usage: jerasure_08 k w seed - Example schedule cache usage with RAID-6\n"); + fprintf(stderr, " \n"); + fprintf(stderr, " m=2. k+m must be <= 2^w. It sets up a RAID-6 generator matrix and encodes\n"); + fprintf(stderr, " k sets of w*%ld bytes. It creates a schedule cache for decoding.\n", sizeof(long)); + fprintf(stderr, " It demonstrates using the schedule cache for both encoding and decoding.\n"); + fprintf(stderr, " Then it demonstrates using jerasure_do_parity() to re-encode the first.\n"); + fprintf(stderr, " coding device\n"); + fprintf(stderr, " \n"); + fprintf(stderr, "This demonstrates: jerasure_generate_schedule_cache()\n"); + fprintf(stderr, " jerasure_smart_bitmatrix_to_schedule()\n"); + fprintf(stderr, " jerasure_schedule_encode()\n"); + fprintf(stderr, " jerasure_schedule_decode_cache()\n"); + fprintf(stderr, " jerasure_free_schedule()\n"); + fprintf(stderr, " jerasure_free_schedule_cache()\n"); + fprintf(stderr, " jerasure_get_stats()\n"); + fprintf(stderr, " jerasure_do_parity()\n"); + if (s != NULL) fprintf(stderr, "%s\n", s); + exit(1); +} + +static void print_array(char **ptrs, int ndevices, int size, int packetsize, char *label) +{ + int i, j, x; + unsigned char *up; + + printf("
\n"); + + for (i = 0; i < ndevices; i++) printf("\n", label, i); + printf("\n"); + printf("\n"); + for (i = 0; i < ndevices; i++) { + printf("\n"); + } + printf("
%s%x
");
+  for (j = 0; j < size/packetsize; j++) printf("Packet %d\n", j);
+  printf("
");
+    up = (unsigned char *) ptrs[i];
+    for (j = 0; j < size/packetsize; j++) {
+      for (x = 0; x < packetsize; x++) {
+        if (x > 0 && x%4 == 0) printf(" ");
+        printf("%02x", up[j*packetsize+x]);
+      }
+      printf("\n");
+    }
+    printf("
\n"); +} + +int main(int argc, char **argv) +{ + int k, w, i, j, m; + int *matrix, *bitmatrix; + char **data, **coding; + int **smart, ***cache; + int *erasures, *erased; + double stats[3]; + uint32_t seed; + + if (argc != 4) usage("Wrong number of arguments"); + if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k"); + if (sscanf(argv[2], "%d", &w) == 0 || w <= 0 || w > 32) usage("Bad m"); + if (sscanf(argv[3], "%d", &seed) == 0) usage("Bad seed"); + m = 2; + if (w < 30 && (k+m) > (1 << w)) usage("k + m is too big"); + + MOA_Seed(seed); + + matrix = talloc(int, m*k); + for (j = 0; j < k; j++) matrix[j] = 1; + i = 1; + for (j = 0; j < k; j++) { + matrix[k+j] = i; + i = galois_single_multiply(i, 2, w); + } + bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix); + + smart = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix); + cache = jerasure_generate_schedule_cache(k, m, w, bitmatrix, 1); + + data = talloc(char *, k); + for (i = 0; i < k; i++) { + data[i] = talloc(char, sizeof(long)*w); + MOA_Fill_Random_Region(data[i], sizeof(long)*w); + } + + coding = talloc(char *, m); + for (i = 0; i < m; i++) { + coding[i] = talloc(char, sizeof(long)*w); + } + + jerasure_schedule_encode(k, m, w, smart, data, coding, w*sizeof(long), sizeof(long)); + jerasure_get_stats(stats); + + printf("jerasure_08"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("\n"); + printf("

jerasure_08"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("

\n"); + printf("
\n"); + + printf("Encoding Complete: - %.0lf XOR'd bytes. Here is the state of the system:\n

\n", stats[0]); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + erasures = talloc(int, (m+1)); + erasures[0] = k; + erasures[1] = k+1; + erasures[2] = -1; + for (j = 0; j < m; j++) bzero(coding[j], sizeof(long)*w); + + jerasure_schedule_decode_cache(k, m, w, cache, erasures, data, coding, w*sizeof(long), sizeof(long)); + jerasure_get_stats(stats); + printf("Encoding Using the Schedule Cache: - %.0lf XOR'd bytes\n\n", stats[0]); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + erased = talloc(int, (k+m)); + for (i = 0; i < m+k; i++) erased[i] = 0; + for (i = 0; i < m; ) { + erasures[i] = MOA_Random_W(w, 1)%(k+m); + if (erased[erasures[i]] == 0) { + erased[erasures[i]] = 1; + bzero((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], sizeof(long)*w); + i++; + } + } + erasures[i] = -1; + + printf("Erased %d random devices:\n\n", m); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + jerasure_schedule_decode_cache(k, m, w, cache, erasures, data, coding, w*sizeof(long), sizeof(long)); + jerasure_get_stats(stats); + + printf("State of the system after decoding: %.0lf XOR'd bytes\n\n", stats[0]); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + bzero(coding[0], sizeof(long)*w); + printf("Erased the first coding device:\n\n"); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + jerasure_do_parity(k, data, coding[0], sizeof(long)*w); + printf("State of the system after using\n"); + printf("jerasure_do_parity() to re-encode it:\n\n"); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + jerasure_free_schedule(smart); + jerasure_free_schedule_cache(k, m, cache); + + printf("Smart schedule and cache freed.\n\n"); + + return 0; +} diff --git a/Examples/liberation_01.c b/Examples/liberation_01.c new file mode 100644 index 0000000..d3b4392 --- /dev/null +++ b/Examples/liberation_01.c @@ -0,0 +1,192 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan. + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank. + */ + +#include +#include +#include +#include +#include +#include "jerasure.h" +#include "liberation.h" + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +static void usage(char *s) +{ + fprintf(stderr, "usage: liberation_01 k w seed - Liberation RAID-6 coding/decoding example in GF(2^w).\n"); + fprintf(stderr, " \n"); + fprintf(stderr, " w must be prime and k <= w. It sets up a Liberation bit-matrix\n"); + fprintf(stderr, " then it encodes k devices of w*%ld bytes using dumb bit-matrix scheduling.\n", sizeof(long)); + fprintf(stderr, " It decodes using smart bit-matrix scheduling.\n"); + fprintf(stderr, " \n"); + fprintf(stderr, "This demonstrates: liberation_coding_bitmatrix()\n"); + fprintf(stderr, " jerasure_smart_bitmatrix_to_schedule()\n"); + fprintf(stderr, " jerasure_dumb_bitmatrix_to_schedule()\n"); + fprintf(stderr, " jerasure_schedule_encode()\n"); + fprintf(stderr, " jerasure_schedule_decode_lazy()\n"); + fprintf(stderr, " jerasure_print_bitmatrix()\n"); + fprintf(stderr, " jerasure_get_stats()\n"); + if (s != NULL) fprintf(stderr, "%s\n", s); + exit(1); +} + +static void print_array(char **ptrs, int ndevices, int size, int packetsize, char *label) +{ + int i, j, x; + unsigned char *up; + + printf("
\n"); + + for (i = 0; i < ndevices; i++) printf("\n", label, i); + printf("\n"); + printf("\n"); + for (i = 0; i < ndevices; i++) { + printf("\n"); + } + printf("
%s%x
");
+  for (j = 0; j < size/packetsize; j++) printf("Packet %d\n", j);
+  printf("
");
+    up = (unsigned char *) ptrs[i];
+    for (j = 0; j < size/packetsize; j++) {
+      for (x = 0; x < packetsize; x++) {
+        if (x > 0 && x%4 == 0) printf(" ");
+        printf("%02x", up[j*packetsize+x]);
+      }
+      printf("\n");
+    }
+    printf("
\n"); +} + +int main(int argc, char **argv) +{ + int k, w, i, m; + int *bitmatrix; + char **data, **coding; + int **dumb; + int *erasures, *erased; + double stats[3]; + uint32_t seed; + + if (argc != 4) usage("Wrong number of arguments"); + if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k"); + if (sscanf(argv[2], "%d", &w) == 0 || w <= 0 || w > 32) usage("Bad w"); + if (sscanf(argv[3], "%u", &seed) == 0) usage("Bad seed"); + m = 2; + if (w < k) usage("k is too big"); + for (i = 2; i*i <= w; i++) if (w%i == 0) usage("w isn't prime"); + + bitmatrix = liberation_coding_bitmatrix(k, w); + if (bitmatrix == NULL) { + usage("couldn't make coding matrix"); + } + + printf("liberation_01"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("\n"); + printf("

liberation_01"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("

\n"); + printf("
\n"); + + printf("Coding Bit-Matrix:\n
\n");
+  jerasure_print_bitmatrix(bitmatrix, w*m, w*k, w);
+  printf("

\n"); + + dumb = jerasure_dumb_bitmatrix_to_schedule(k, m, w, bitmatrix); + + MOA_Seed(seed); + data = talloc(char *, k); + for (i = 0; i < k; i++) { + data[i] = talloc(char, sizeof(long)*w); + MOA_Fill_Random_Region(data[i], sizeof(long)*w); + } + + coding = talloc(char *, m); + for (i = 0; i < m; i++) { + coding[i] = talloc(char, sizeof(long)*w); + } + + jerasure_schedule_encode(k, m, w, dumb, data, coding, w*sizeof(long), sizeof(long)); + jerasure_get_stats(stats); + printf("Smart Encoding Complete: - %.0lf XOR'd bytes. State of the system:\n\n", stats[0]); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + erasures = talloc(int, (m+1)); + erased = talloc(int, (k+m)); + for (i = 0; i < m+k; i++) erased[i] = 0; + for (i = 0; i < m; ) { + erasures[i] = MOA_Random_W(30,1)%(k+m); + if (erased[erasures[i]] == 0) { + erased[erasures[i]] = 1; + bzero((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], sizeof(long)*w); + i++; + } + } + erasures[i] = -1; + + printf("Erased %d random devices:\n\n", m); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + jerasure_schedule_decode_lazy(k, m, w, bitmatrix, erasures, data, coding, w*sizeof(long), sizeof(long), 1); + jerasure_get_stats(stats); + + printf("State of the system after decoding: %.0lf XOR'd bytes\n\n", stats[0]); + printf("

\n"); + print_array(data, k, sizeof(long)*w, sizeof(long), "D"); + printf("

\n"); + print_array(coding, m, sizeof(long)*w, sizeof(long), "C"); + printf("


\n"); + + return 0; +} diff --git a/Examples/reed_sol_01.c b/Examples/reed_sol_01.c new file mode 100644 index 0000000..da46aeb --- /dev/null +++ b/Examples/reed_sol_01.c @@ -0,0 +1,195 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan. + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank. + */ + +#include +#include +#include +#include +#include +#include "jerasure.h" +#include "reed_sol.h" + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +static void usage(char *s) +{ + fprintf(stderr, "usage: reed_sol_01 k m w seed - Does a simple Reed-Solomon coding example in GF(2^w).\n"); + fprintf(stderr, " \n"); + fprintf(stderr, "w must be 8, 16 or 32. k+m must be <= 2^w. It sets up a classic\n"); + fprintf(stderr, "Vandermonde-based generator matrix and encodes k devices of\n"); + fprintf(stderr, "%ld bytes each with it. Then it decodes.\n", sizeof(long)); + fprintf(stderr, " \n"); + fprintf(stderr, "This demonstrates: jerasure_matrix_encode()\n"); + fprintf(stderr, " jerasure_matrix_decode()\n"); + fprintf(stderr, " jerasure_print_matrix()\n"); + fprintf(stderr, " reed_sol_vandermonde_coding_matrix()\n"); + if (s != NULL) fprintf(stderr, "%s\n", s); + exit(1); +} + +static void print_data_and_coding(int k, int m, int w, int size, + char **data, char **coding) +{ + int i, j, x; + int n, sp; + + if(k > m) n = k; + else n = m; + sp = size * 2 + size/(w/8) + 8; + + printf("%-*sCoding\n", sp, "Data"); + for(i = 0; i < n; i++) { + if(i < k) { + printf("D%-2d:", i); + for(j=0;j< size; j+=(w/8)) { + printf(" "); + for(x=0;x < w/8;x++){ + printf("%02x", (unsigned char)data[i][j+x]); + } + } + printf(" "); + } + else printf("%*s", sp, ""); + if(i < m) { + printf("C%-2d:", i); + for(j=0;j< size; j+=(w/8)) { + printf(" "); + for(x=0;x < w/8;x++){ + printf("%02x", (unsigned char)coding[i][j+x]); + } + } + } + printf("\n"); + } + printf("\n"); +} + +int main(int argc, char **argv) +{ + long l; + int k, w, i, j, m; + int *matrix; + char **data, **coding, **dcopy, **ccopy; + unsigned char uc; + int *erasures, *erased; + uint32_t seed; + + if (argc != 5) usage(NULL); + if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k"); + if (sscanf(argv[2], "%d", &m) == 0 || m <= 0) usage("Bad m"); + if (sscanf(argv[3], "%d", &w) == 0 || (w != 8 && w != 16 && w != 32)) usage("Bad w"); + if (sscanf(argv[4], "%u", &seed) == 0) usage("Bad seed"); + if (w <= 16 && k + m > (1 << w)) usage("k + m is too big"); + + matrix = reed_sol_vandermonde_coding_matrix(k, m, w); + + printf("reed_sol_01 %d %d %d %d\n", k, m, w, seed); + printf("

reed_sol_01 %d %d %d %d

\n", k, m, w, seed); + printf("
\n");
+  printf("Last m rows of the generator Matrix (G^T):\n\n");
+  jerasure_print_matrix(matrix, m, k, w);
+  printf("\n");
+
+  MOA_Seed(seed);
+  data = talloc(char *, k);
+  dcopy = talloc(char *, k);
+  for (i = 0; i < k; i++) {
+    data[i] = talloc(char, sizeof(long));
+    dcopy[i] = talloc(char, sizeof(long));
+    for (j = 0; j < sizeof(long); j++) {
+      uc = MOA_Random_W(8, 1);
+      data[i][j] = (char) uc;
+    }
+    memcpy(dcopy[i], data[i], sizeof(long));
+  }
+
+  coding = talloc(char *, m);
+  ccopy = talloc(char *, m);
+  for (i = 0; i < m; i++) {
+    coding[i] = talloc(char, sizeof(long));
+    ccopy[i] = talloc(char, sizeof(long));
+  }
+
+  jerasure_matrix_encode(k, m, w, matrix, data, coding, sizeof(long));
+
+  for (i = 0; i < m; i++) {
+    memcpy(ccopy[i], coding[i], sizeof(long));
+  }
+  
+  printf("Encoding Complete:\n\n");
+  print_data_and_coding(k, m, w, sizeof(long), data, coding);
+
+  erasures = talloc(int, (m+1));
+  erased = talloc(int, (k+m));
+  for (i = 0; i < m+k; i++) erased[i] = 0;
+  l = 0;
+  for (i = 0; i < m; ) {
+    erasures[i] = MOA_Random_W(31, 0)%(k+m);
+    if (erased[erasures[i]] == 0) {
+      erased[erasures[i]] = 1;
+      memcpy((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], &l, sizeof(long));
+      i++;
+    }
+  }
+  erasures[i] = -1;
+
+  printf("Erased %d random devices:\n\n", m);
+  print_data_and_coding(k, m, w, sizeof(long), data, coding);
+  
+  i = jerasure_matrix_decode(k, m, w, matrix, 1, erasures, data, coding, sizeof(long));
+
+  printf("State of the system after decoding:\n\n");
+  print_data_and_coding(k, m, w, sizeof(long), data, coding);
+  
+  for (i = 0; i < k; i++) if (memcmp(data[i], dcopy[i], sizeof(long)) != 0) {
+    printf("ERROR: D%x after decoding does not match its state before decoding!
\n", i); + } + for (i = 0; i < m; i++) if (memcmp(coding[i], ccopy[i], sizeof(long)) != 0) { + printf("ERROR: C%x after decoding does not match its state before decoding!
\n", i); + } + + return 0; +} diff --git a/Examples/reed_sol_02.c b/Examples/reed_sol_02.c new file mode 100644 index 0000000..6beb4f6 --- /dev/null +++ b/Examples/reed_sol_02.c @@ -0,0 +1,104 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan. + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank. + */ + +#include +#include +#include +#include "jerasure.h" +#include "reed_sol.h" + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +static void usage(char *s) +{ + fprintf(stderr, "usage: reed_sol_02 k m w - Vandermonde matrices in GF(2^w).\n"); + fprintf(stderr, " \n"); + fprintf(stderr, " k+m must be <= 2^w. This simply prints out the \n"); + fprintf(stderr, " Vandermonde matrix in GF(2^w), and then the generator\n"); + fprintf(stderr, " matrix that is constructed from it. See [Plank-Ding-05] for\n"); + fprintf(stderr, " information on how this construction proceeds\n"); + fprintf(stderr, " \n"); + fprintf(stderr, "This demonstrates: reed_sol_extended_vandermonde_matrix()\n"); + fprintf(stderr, " reed_sol_big_vandermonde_coding_matrix()\n"); + fprintf(stderr, " reed_sol_vandermonde_coding_matrix()\n"); + fprintf(stderr, " jerasure_print_matrix()\n"); + if (s != NULL) fprintf(stderr, "%s\n", s); + exit(1); +} + +int main(int argc, char **argv) +{ + int k, w, m; + int *matrix; + + if (argc != 4) usage(NULL); + if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k"); + if (sscanf(argv[2], "%d", &m) == 0 || m <= 0) usage("Bad m"); + if (sscanf(argv[3], "%d", &w) == 0 || w <= 0 || w > 32) usage("Bad w"); + if (w <= 30 && k + m > (1 << w)) usage("k + m is too big"); + + matrix = reed_sol_extended_vandermonde_matrix(k+m, k, w); + + printf("reed_sol_02 %d %d %d\n", k, m, w); + printf("

reed_sol_02 %d %d %d

\n", k, m, w); + printf("
\n");
+  printf("Extended Vandermonde Matrix:\n\n");
+  jerasure_print_matrix(matrix, k+m, k, w);
+  printf("\n");
+
+  matrix = reed_sol_big_vandermonde_distribution_matrix(k+m, k, w);
+  printf("Vandermonde Generator Matrix (G^T):\n\n");
+  jerasure_print_matrix(matrix, k+m, k, w);
+  printf("\n");
+
+  matrix = reed_sol_vandermonde_coding_matrix(k, m, w);
+  printf("Vandermonde Coding Matrix:\n\n");
+  jerasure_print_matrix(matrix, m, k, w);
+  printf("\n");
+
+  
+  return 0;
+}
diff --git a/Examples/reed_sol_03.c b/Examples/reed_sol_03.c
new file mode 100644
index 0000000..187cebd
--- /dev/null
+++ b/Examples/reed_sol_03.c
@@ -0,0 +1,195 @@
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Jerasure's authors:
+
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan.
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include "jerasure.h"
+#include "reed_sol.h"
+
+#define talloc(type, num) (type *) malloc(sizeof(type)*(num))
+
+static void usage(char *s)
+{
+  fprintf(stderr, "usage: reed_sol_03 k w seed - Does a simple RAID-6 coding example in GF(2^w).\n");
+  fprintf(stderr, "       \n");
+  fprintf(stderr, "       w must be 8, 16 or 32.  k+2 must be <= 2^w.  It sets up a classic\n");
+  fprintf(stderr, "       RAID-6 coding matrix based on Anvin's optimization and encodes\n");
+  fprintf(stderr, "       %ld-byte devices with it.  Then it decodes.\n", sizeof(long));
+  fprintf(stderr, "       \n");
+  fprintf(stderr, "This demonstrates: reed_sol_r6_encode()\n");
+  fprintf(stderr, "                   reed_sol_r6_coding_matrix()\n");
+  fprintf(stderr, "                   jerasure_matrix_decode()\n");
+  fprintf(stderr, "                   jerasure_print_matrix()\n");
+  if (s != NULL) fprintf(stderr, "%s\n", s);
+  exit(1);
+}
+
+
+static void print_data_and_coding(int k, int m, int w, int size, 
+		char **data, char **coding) 
+{
+  int i, j, x;
+  int n, sp;
+
+  if(k > m) n = k;
+  else n = m;
+  sp = size * 2 + size/(w/8) + 8;
+
+  printf("%-*sCoding\n", sp, "Data");
+  for(i = 0; i < n; i++) {
+	  if(i < k) {
+		  printf("D%-2d:", i);
+		  for(j=0;j< size; j+=(w/8)) { 
+			  printf(" ");
+			  for(x=0;x < w/8;x++){
+				printf("%02x", (unsigned char)data[i][j+x]);
+			  }
+		  }
+		  printf("    ");
+	  }
+	  else printf("%*s", sp, "");
+	  if(i < m) {
+		  printf("C%-2d:", i);
+		  for(j=0;j< size; j+=(w/8)) { 
+			  printf(" ");
+			  for(x=0;x < w/8;x++){
+				printf("%02x", (unsigned char)coding[i][j+x]);
+			  }
+		  }
+	  }
+	  printf("\n");
+  }
+	printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+  long l;
+  unsigned char uc;
+  int k, w, i, j, m;
+  int *matrix;
+  char **data, **coding, **dcopy, **ccopy;
+  int *erasures, *erased;
+  uint32_t seed;
+  
+  if (argc != 4) usage(NULL);
+  if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k");
+  if (sscanf(argv[2], "%d", &w) == 0 || (w != 8 && w != 16 && w != 32)) usage("Bad w");
+  if (sscanf(argv[3], "%d", &seed) == 0) usage("Bad seed");
+  m = 2;
+  if (w <= 16 && k + m > (1 << w)) usage("k + m is too big");
+
+  MOA_Seed(seed);
+  matrix = reed_sol_r6_coding_matrix(k, w);
+
+  printf("reed_sol_03 %d %d %d\n", k, w, seed);
+  printf("

reed_sol_03 %d %d %d

\n", k, w, seed); + printf("
\n");
+
+  printf("Last 2 rows of the Generator Matrix:\n\n");
+  jerasure_print_matrix(matrix, m, k, w);
+  printf("\n");
+
+  data = talloc(char *, k);
+  dcopy = talloc(char *, k);
+  for (i = 0; i < k; i++) {
+    data[i] = talloc(char, sizeof(long));
+    dcopy[i] = talloc(char, sizeof(long));
+    for (j = 0; j < sizeof(long); j++) {
+      uc = MOA_Random_W(8, 1) %256;
+      data[i][j] = (char) uc;   
+    }
+    memcpy(dcopy[i], data[i], sizeof(long));
+  }
+
+  coding = talloc(char *, m);
+  ccopy = talloc(char *, m);
+  for (i = 0; i < m; i++) {
+    coding[i] = talloc(char, sizeof(long));
+    ccopy[i] = talloc(char, sizeof(long));
+  }
+
+  reed_sol_r6_encode(k, w, data, coding, sizeof(long));
+  for (i = 0; i < m; i++) {
+    memcpy(ccopy[i], coding[i], sizeof(long));
+  }
+  
+  printf("Encoding Complete:\n\n");
+  print_data_and_coding(k, m, w, sizeof(long), data, coding);
+
+  erasures = talloc(int, (m+1));
+  erased = talloc(int, (k+m));
+  for (i = 0; i < m+k; i++) erased[i] = 0;
+  l = 0;
+  for (i = 0; i < m; ) {
+    erasures[i] = ((unsigned int) MOA_Random_W(w, 1))%(k+m);
+    if (erased[erasures[i]] == 0) {
+      erased[erasures[i]] = 1;
+      memcpy((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], &l, sizeof(long));
+      i++;
+    }
+  }
+  erasures[i] = -1;
+
+  printf("Erased %d random devices:\n\n", m);
+  print_data_and_coding(k, m, w, sizeof(long), data, coding);
+  
+  i = jerasure_matrix_decode(k, m, w, matrix, 1, erasures, data, coding, sizeof(long));
+
+  printf("State of the system after decoding:\n\n");
+  print_data_and_coding(k, m, w, sizeof(long), data, coding);
+  
+  for (i = 0; i < k; i++) if (memcmp(data[i], dcopy[i], sizeof(long)) != 0) {
+    printf("ERROR: D%x after decoding does not match its state before decoding!
\n", i); + } + for (i = 0; i < m; i++) if (memcmp(coding[i], ccopy[i], sizeof(long)) != 0) { + printf("ERROR: C%x after decoding does not match its state before decoding!
\n", i); + } + + return 0; +} diff --git a/Examples/reed_sol_04.c b/Examples/reed_sol_04.c new file mode 100644 index 0000000..f763fb0 --- /dev/null +++ b/Examples/reed_sol_04.c @@ -0,0 +1,120 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan. + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank. + */ + +#include +#include +#include +#include +#include +#include "jerasure.h" +#include "reed_sol.h" + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +static void usage(char *s) +{ + fprintf(stderr, "usage: reed_sol_04 w seed - Shows reed_sol_galois_wXX_region_multby_2\n"); + fprintf(stderr, " \n"); + fprintf(stderr, " w must be 8, 16 or 32. Sets up an array of 4 random words in\n"); + fprintf(stderr, " GF(2^w) and multiplies them by two. \n"); + fprintf(stderr, " \n"); + fprintf(stderr, "This demonstrates: reed_sol_galois_w08_region_multby_2()\n"); + fprintf(stderr, " reed_sol_galois_w16_region_multby_2()\n"); + fprintf(stderr, " reed_sol_galois_w32_region_multby_2()\n"); + if (s != NULL) fprintf(stderr, "%s\n", s); + exit(1); +} + +int main(int argc, char **argv) +{ + unsigned char *x, *y; + unsigned short *xs, *ys; + unsigned int *xi, *yi; + uint32_t seed; + int *a32, *copy; + int i; + int w; + + if (argc != 3) usage(NULL); + if (sscanf(argv[1], "%d", &w) == 0 || (w != 8 && w != 16 && w != 32)) usage("Bad w"); + if (sscanf(argv[2], "%d", &seed) == 0) usage("Bad seed"); + + printf("reed_sol_04 %d %d\n", w, seed); + printf("

reed_sol_04 %d %d

\n", w, seed); + printf("
\n");
+
+  MOA_Seed(seed);
+  a32 = talloc(int, 4);
+  copy = talloc(int, 4);
+  y = (unsigned char *) a32;
+  for (i = 0; i < 4*sizeof(int); i++) y[i] = MOA_Random_W(8, 1);
+  memcpy(copy, a32, sizeof(int)*4);
+
+  if (w == 8) {
+    x = (unsigned char *) copy;
+    y = (unsigned char *) a32;
+    reed_sol_galois_w08_region_multby_2((char *) a32, sizeof(int)*4);
+    for (i = 0; i < 4*sizeof(int)/sizeof(char); i++) {
+       printf("Char %2d: %3u *2 = %3u\n", i, x[i], y[i]);
+    }
+  } else if (w == 16) {
+    xs = (unsigned short *) copy;
+    ys = (unsigned short *) a32;
+    reed_sol_galois_w16_region_multby_2((char *) a32, sizeof(int)*4);
+    for (i = 0; i < 4*sizeof(int)/sizeof(short); i++) {
+       printf("Short %2d: %5u *2 = %5u\n", i, xs[i], ys[i]);
+    }
+  } else if (w == 32) {
+    xi = (unsigned int *) copy;
+    yi = (unsigned int *) a32;
+    reed_sol_galois_w16_region_multby_2((char *) a32, sizeof(int)*4);
+    for (i = 0; i < 4*sizeof(int)/sizeof(int); i++) {
+       printf("Int %2d: %10u *2 = %10u\n", i, xi[i], yi[i]);
+    }
+  } 
+
+  return 0;
+}
diff --git a/Examples/reed_sol_test_gf.c b/Examples/reed_sol_test_gf.c
new file mode 100644
index 0000000..9e8856c
--- /dev/null
+++ b/Examples/reed_sol_test_gf.c
@@ -0,0 +1,191 @@
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Jerasure's authors:
+
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan.
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "jerasure.h"
+#include "reed_sol.h"
+
+#define BUFSIZE 4096
+
+static void *malloc16(int size) {
+    void *mem = malloc(size+16+sizeof(void*));
+    void **ptr = (void**)((long)(mem+16+sizeof(void*)) & ~(15));
+    ptr[-1] = mem;
+    return ptr;
+}
+
+#if 0
+// Unused for now.
+static void free16(void *ptr) {
+    free(((void**)ptr)[-1]);
+}
+#endif
+
+#define talloc(type, num) (type *) malloc16(sizeof(type)*(num))
+
+static void usage(char *s)
+{
+  fprintf(stderr, "usage: reed_sol_test_gf k m w seed (additional GF args) - Tests Reed-Solomon in GF(2^w).\n");
+  fprintf(stderr, "       \n");
+  fprintf(stderr, "       w must be 8, 16 or 32.  k+m must be <= 2^w.\n");
+  fprintf(stderr, "       See the README for information on the additional GF args.\n");
+  fprintf(stderr, "       Set up a Vandermonde-based distribution matrix and encodes k devices of\n");
+  fprintf(stderr, "       %d bytes each with it.  Then it decodes.\n", BUFSIZE);
+  fprintf(stderr, "       \n");
+  fprintf(stderr, "This tests:        jerasure_matrix_encode()\n");
+  fprintf(stderr, "                   jerasure_matrix_decode()\n");
+  fprintf(stderr, "                   jerasure_print_matrix()\n");
+  fprintf(stderr, "                   galois_change_technique()\n");
+  fprintf(stderr, "                   reed_sol_vandermonde_coding_matrix()\n");
+  if (s != NULL) fprintf(stderr, "%s\n", s);
+  exit(1);
+}
+
+gf_t* get_gf(int w, int argc, char **argv, int starting)
+{
+  gf_t *gf = (gf_t*)malloc(sizeof(gf_t));
+  if (create_gf_from_argv(gf, w, argc, argv, starting) == 0) {
+    free(gf);
+    gf = NULL;
+  }
+  return gf;
+}
+
+int main(int argc, char **argv)
+{
+  int k, w, i, m;
+  int *matrix;
+  char **data, **coding, **old_values;
+  int *erasures, *erased;
+  gf_t *gf = NULL;
+  uint32_t seed;
+  
+  if (argc < 6) usage("Not enough command line arguments");  
+  if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k");
+  if (sscanf(argv[2], "%d", &m) == 0 || m <= 0) usage("Bad m");
+  if (sscanf(argv[3], "%d", &w) == 0 || (w != 8 && w != 16 && w != 32)) usage("Bad w");
+  if (sscanf(argv[4], "%d", &seed) == 0) usage("Bad seed");
+  if (w <= 16 && k + m > (1 << w)) usage("k + m is too big");
+
+  MOA_Seed(seed);
+
+  gf = get_gf(w, argc, argv, 5); 
+
+  if (gf == NULL) {
+    usage("Invalid arguments given for GF!\n");
+  }
+
+  galois_change_technique(gf, w); 
+
+  matrix = reed_sol_vandermonde_coding_matrix(k, m, w);
+
+  printf("reed_sol_test_gf");
+  for (i = 1; i < argc; i++) printf(" %s", argv[i]);
+  printf("\n");
+  printf("

reed_sol_test_gf"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("

\n"); + printf("
\n");
+
+  printf("Last m rows of the generator matrix (G^T):\n\n");
+  jerasure_print_matrix(matrix, m, k, w);
+  printf("\n");
+
+  data = talloc(char *, k);
+  for (i = 0; i < k; i++) {
+    data[i] = talloc(char, BUFSIZE);
+    MOA_Fill_Random_Region(data[i], BUFSIZE);
+  }
+
+  coding = talloc(char *, m);
+  old_values = talloc(char *, m);
+  for (i = 0; i < m; i++) {
+    coding[i] = talloc(char, BUFSIZE);
+    old_values[i] = talloc(char, BUFSIZE);
+  }
+
+  jerasure_matrix_encode(k, m, w, matrix, data, coding, BUFSIZE);
+  
+  erasures = talloc(int, (m+1));
+  erased = talloc(int, (k+m));
+  for (i = 0; i < m+k; i++) erased[i] = 0;
+  for (i = 0; i < m; ) {
+    erasures[i] = ((unsigned int)MOA_Random_W(w,1))%(k+m);
+    if (erased[erasures[i]] == 0) {
+      erased[erasures[i]] = 1;
+      memcpy(old_values[i], (erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], BUFSIZE);
+      bzero((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], BUFSIZE);
+      i++;
+    }
+  }
+  erasures[i] = -1;
+
+  i = jerasure_matrix_decode(k, m, w, matrix, 1, erasures, data, coding, BUFSIZE);
+
+  for (i = 0; i < m; i++) {
+    if (erasures[i] < k) {
+      if (memcmp(data[erasures[i]], old_values[i], BUFSIZE)) {
+        fprintf(stderr, "Decoding failed for %d!\n", erasures[i]);
+        exit(1);
+      }
+    } else {
+      if (memcmp(coding[erasures[i]-k], old_values[i], BUFSIZE)) {
+        fprintf(stderr, "Decoding failed for %d!\n", erasures[i]);
+        exit(1);
+      }
+    }
+  }
+  
+  printf("Encoding and decoding were both successful.\n");
+  return 0;
+}
diff --git a/Examples/reed_sol_time_gf.c b/Examples/reed_sol_time_gf.c
new file mode 100644
index 0000000..175de8b
--- /dev/null
+++ b/Examples/reed_sol_time_gf.c
@@ -0,0 +1,204 @@
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Jerasure's authors:
+
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan.
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "jerasure.h"
+#include "reed_sol.h"
+#include "timing.h"
+
+static void *malloc16(int size) {
+    void *mem = malloc(size+16+sizeof(void*));
+    void **ptr = (void**)((long)(mem+16+sizeof(void*)) & ~(15));
+    ptr[-1] = mem;
+    return ptr;
+}
+
+#if 0
+// Unused for now.
+static void free16(void *ptr) {
+    free(((void**)ptr)[-1]);
+}
+#endif
+
+#define talloc(type, num) (type *) malloc16(sizeof(type)*(num))
+
+static void usage(char *s)
+{
+  fprintf(stderr, "usage: reed_sol_time_gf k m w seed iterations bufsize (additional GF args) - Test and time Reed-Solomon in a particular GF(2^w).\n");
+  fprintf(stderr, "       \n");
+  fprintf(stderr, "       w must be 8, 16 or 32.  k+m must be <= 2^w.\n");
+  fprintf(stderr, "       See the README for information on the additional GF args.\n");
+  fprintf(stderr, "       Set up a Vandermonde-based distribution matrix and encodes k devices of\n");
+  fprintf(stderr, "       bufsize bytes each with it.  Then it decodes.\n");
+  fprintf(stderr, "       \n");
+  fprintf(stderr, "This tests:        jerasure_matrix_encode()\n");
+  fprintf(stderr, "                   jerasure_matrix_decode()\n");
+  fprintf(stderr, "                   jerasure_print_matrix()\n");
+  fprintf(stderr, "                   galois_change_technique()\n");
+  fprintf(stderr, "                   reed_sol_vandermonde_coding_matrix()\n");
+  if (s != NULL) fprintf(stderr, "%s\n", s);
+  exit(1);
+}
+
+gf_t* get_gf(int w, int argc, char **argv, int starting)
+{
+  gf_t *gf = (gf_t*)malloc(sizeof(gf_t));
+  if (create_gf_from_argv(gf, w, argc, argv, starting) == 0) {
+    free(gf);
+    gf = NULL;
+  }
+  return gf;
+}
+
+int main(int argc, char **argv)
+{
+  int k, w, i, m, iterations, bufsize;
+  int *matrix;
+  char **data, **coding, **old_values;
+  int *erasures, *erased;
+  uint32_t seed;
+  double t = 0, total_time = 0;
+  gf_t *gf = NULL;
+  
+  if (argc < 8) usage(NULL);  
+  if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k");
+  if (sscanf(argv[2], "%d", &m) == 0 || m <= 0) usage("Bad m");
+  if (sscanf(argv[3], "%d", &w) == 0 || (w != 8 && w != 16 && w != 32)) usage("Bad w");
+  if (sscanf(argv[4], "%d", &seed) == 0) usage("Bad seed");
+  if (sscanf(argv[5], "%d", &iterations) == 0) usage("Bad iterations");
+  if (sscanf(argv[6], "%d", &bufsize) == 0) usage("Bad bufsize");
+  if (w <= 16 && k + m > (1 << w)) usage("k + m is too big");
+
+  MOA_Seed(seed);
+
+  gf = get_gf(w, argc, argv, 7); 
+
+  if (gf == NULL) {
+    usage("Invalid arguments given for GF!\n");
+  }
+
+  galois_change_technique(gf, w); 
+
+  matrix = reed_sol_vandermonde_coding_matrix(k, m, w);
+
+  printf("reed_sol_time_gf");
+  for (i = 1; i < argc; i++) printf(" %s", argv[i]);
+  printf("\n");
+  printf("

reed_sol_time_gf"); + for (i = 1; i < argc; i++) printf(" %s", argv[i]); + printf("

\n"); + printf("
\n");
+
+  printf("Last m rows of the generator matrix (G^T):\n\n");
+  jerasure_print_matrix(matrix, m, k, w);
+  printf("\n");
+
+  data = talloc(char *, k);
+  for (i = 0; i < k; i++) {
+    data[i] = talloc(char, bufsize);
+    MOA_Fill_Random_Region(data[i], bufsize);
+  }
+
+  coding = talloc(char *, m);
+  old_values = talloc(char *, m);
+  for (i = 0; i < m; i++) {
+    coding[i] = talloc(char, bufsize);
+    old_values[i] = talloc(char, bufsize);
+  }
+
+  for (i = 0; i < iterations; i++) {
+    t = timing_now();
+    jerasure_matrix_encode(k, m, w, matrix, data, coding, bufsize);
+    total_time += timing_now() - t;
+  }
+
+  printf("Encode throughput for %d iterations: %.2f MB/s (%.2f sec)\n", iterations, (double)(k*iterations*bufsize/1024/1024) / total_time, total_time);
+  
+  erasures = talloc(int, (m+1));
+  erased = talloc(int, (k+m));
+  for (i = 0; i < m+k; i++) erased[i] = 0;
+  for (i = 0; i < m; ) {
+    erasures[i] = ((unsigned int)MOA_Random_W(w, 1))%(k+m);
+    if (erased[erasures[i]] == 0) {
+      erased[erasures[i]] = 1;
+      memcpy(old_values[i], (erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], bufsize);
+      bzero((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], bufsize);
+      i++;
+    }
+  }
+  erasures[i] = -1;
+
+  for (i = 0; i < iterations; i++) {
+    t = timing_now();
+    jerasure_matrix_decode(k, m, w, matrix, 1, erasures, data, coding, bufsize);
+    total_time += timing_now() - t;
+  }
+  
+  printf("Decode throughput for %d iterations: %.2f MB/s (%.2f sec)\n", iterations, (double)(k*iterations*bufsize/1024/1024) / total_time, total_time);
+
+  for (i = 0; i < m; i++) {
+    if (erasures[i] < k) {
+      if (memcmp(data[erasures[i]], old_values[i], bufsize)) {
+        fprintf(stderr, "Decoding failed for %d!\n", erasures[i]);
+        exit(1);
+      }
+    } else {
+      if (memcmp(coding[erasures[i]-k], old_values[i], bufsize)) {
+        fprintf(stderr, "Decoding failed for %d!\n", erasures[i]);
+        exit(1);
+      }
+    }
+  }
+  
+  return 0;
+}
diff --git a/Examples/test_all_gfs.sh b/Examples/test_all_gfs.sh
new file mode 100755
index 0000000..b78dd6b
--- /dev/null
+++ b/Examples/test_all_gfs.sh
@@ -0,0 +1,98 @@
+#!/bin/bash
+#
+# Copyright (c) 2013, James S. Plank and Kevin Greenan
+# All rights reserved.
+#
+# Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+# Coding Techniques
+#
+# Revision 2.0: Galois Field backend now links to GF-Complete
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#  - Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#
+#  - Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+#  - Neither the name of the University of Tennessee nor the names of its
+#    contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+GF_METHODS=${GF_COMPLETE_DIR:-/usr/local/bin}/gf_methods
+k=12
+m=3
+seed=1370
+
+if ! test -x ${GF_METHODS} ; then
+    ${GF_METHODS}
+    exit 1
+fi
+
+# Test all w=8
+${GF_METHODS} 8 -B -L | awk -F: '{ if ($1 == "w=8") print $2; }' |
+while read method; do
+  echo "Testing ${k} ${m} 8 $seed ${method}"
+  $VALGRIND ./reed_sol_test_gf ${k} ${m} 8 $seed ${method} | tail -n 1
+  if [[ $? != "0" ]]; then
+    echo "Failed test for ${k} ${m} 8 $seed ${method}"
+    exit 1
+  fi
+done
+
+if [[ $? == "1" ]]; then
+  exit 1
+fi
+
+
+# Test all w=16
+${GF_METHODS} 16 -B -L | awk -F: '{ if ($1 == "w=16") print $2; }' |
+while read method; do
+  echo "Testing ${k} ${m} 16 $seed ${method}"
+  $VALGRIND ./reed_sol_test_gf ${k} ${m} 16 $seed ${method} | tail -n 1
+  if [[ $? != "0" ]]; then
+    echo "Failed test for ${k} ${m} 16 $seed ${method}"
+    exit 1
+  fi
+done
+
+
+if [[ $? == "1" ]]; then
+  exit 1
+fi
+
+# Test all w=32
+${GF_METHODS} 32 -B -L | awk -F: '{ if ($1 == "w=32") print $2; }' |
+while read method; do
+  echo "Testing ${k} ${m} 32 $seed ${method}"
+  $VALGRIND ./reed_sol_test_gf ${k} ${m} 32 $seed ${method} | tail -n 1
+  if [[ $? != "0" ]]; then
+    echo "Failed test for ${k} ${m} 32 $seed ${method}"
+    exit 1
+  fi
+done
+
+
+if [[ $? == "1" ]]; then
+  exit 1
+fi
+
+echo "Passed all tests!"
diff --git a/Examples/test_galois.c b/Examples/test_galois.c
new file mode 100644
index 0000000..a913a77
--- /dev/null
+++ b/Examples/test_galois.c
@@ -0,0 +1,23 @@
+#include 
+#include "galois.h"
+
+int main(int argc, char **argv)
+{
+  assert(galois_init_default_field(4) == 0);
+  assert(galois_uninit_field(4) == 0);
+  assert(galois_init_default_field(4) == 0);
+  assert(galois_uninit_field(4) == 0);
+
+  assert(galois_init_default_field(8) == 0);
+  assert(galois_uninit_field(8) == 0);
+  assert(galois_init_default_field(8) == 0);
+  assert(galois_uninit_field(8) == 0);
+
+  return 0;
+}
+/*
+ * Local Variables:
+ * compile-command: "make test_galois && 
+ *    libtool --mode=execute valgrind --tool=memcheck --leak-check=full ./test_galois"
+ * End:
+ */
diff --git a/Examples/time_all_gfs_argv_init.sh b/Examples/time_all_gfs_argv_init.sh
new file mode 100755
index 0000000..737652a
--- /dev/null
+++ b/Examples/time_all_gfs_argv_init.sh
@@ -0,0 +1,64 @@
+#
+#
+# Copyright (c) 2013, James S. Plank and Kevin Greenan
+# All rights reserved.
+#
+# Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+# Coding Techniques
+#
+# Revision 2.0: Galois Field backend now links to GF-Complete
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#  - Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#
+#  - Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+#  - Neither the name of the University of Tennessee nor the names of its
+#    contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+GF_COMPLETE_DIR=/usr/local/bin
+GF_METHODS=${GF_COMPLETE_DIR}/gf_methods
+ITERATIONS=128
+BUFSIZE=65536
+k=12
+m=3
+seed=1370
+
+for w in 8 16 32 ; do 
+  ${GF_METHODS} $w -B -L | awk -F: '{ if ($1 == "w='$w'") print $2; }' |
+  while read method; do
+    echo "Testing ${k} ${m} ${w} ${seed} ${ITERATIONS} ${BUFSIZE} ${method}"
+    ./reed_sol_time_gf ${k} ${m} ${w} ${seed} ${ITERATIONS} ${BUFSIZE} ${method} | tail -n 2
+    if [[ $? != "0" ]]; then
+      echo "Failed test for ${k} ${m} ${w} ${seed} ${ITERATIONS} ${BUFSIZE} ${method}"
+      exit 1
+    fi
+  done
+
+  if [[ $? == "1" ]]; then
+    exit 1
+  fi
+done
+
+echo "Passed all tests!"
diff --git a/License.txt b/License.txt
new file mode 100644
index 0000000..20ffbd2
--- /dev/null
+++ b/License.txt
@@ -0,0 +1,37 @@
+
+Copyright (c) 2013, James S. Plank and Kevin Greenan
+All rights reserved.
+
+Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques
+
+Revision 2.0: Galois Field backend now links to GF-Complete
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in
+   the documentation and/or other materials provided with the
+   distribution.
+
+ - Neither the name of the University of Tennessee nor the names of its
+   contributors may be used to endorse or promote products derived
+   from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..e79f464
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,5 @@
+# Jerasure Automake file
+
+SUBDIRS = src Examples
+
+EXTRA_DIST = Manual.pdf PERF.txt
diff --git a/Manual.pdf b/Manual.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..e596023e538461064b35cc2ea7622b3498f4a2a7
GIT binary patch
literal 409116
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

d2dWl) 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%0Dyz@f!=tILX_w0 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%0Ao?~Mv@)0O>G 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 literal 0 HcmV?d00001 diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/PERF.txt b/PERF.txt new file mode 100644 index 0000000..ee27826 --- /dev/null +++ b/PERF.txt @@ -0,0 +1,243 @@ +This reflects time_all_gfs_argv_init.sh run on a MacBook Air with 4 GB of memory and a 1.7 GHz Intel Core i5 + +#uname -a +11.4.2 Darwin Kernel Version 11.4.2: Thu Aug 23 16:25:48 PDT 2012; root:xnu-1699.32.7~1/RELEASE_X86_64 x86_64 + + + +_12_3_8_128_65536_-m_SPLIT_8_4_-r_SSE_- 2813.34 +_12_3_8_128_65536_-m_COMPOSITE_2_-_-r_ALTMAP_- 2808.39 +_12_3_8_128_65536_- 2797.62 +_12_3_8_128_65536_-m_SPLIT_8_4_- 2793.14 +_12_3_8_128_65536_-m_SPLIT_8_4_-r_SSE_-d_EUCLID_- 2779.97 +_12_3_8_128_65536_-m_SPLIT_8_4_-d_EUCLID_- 2776.50 +_12_3_8_128_65536_-m_SPLIT_8_4_-d_MATRIX_- 2762.82 +_12_3_8_128_65536_-m_SPLIT_8_4_-r_SSE_-d_MATRIX_- 2711.49 +_12_3_16_128_65536_-m_COMPOSITE_2_-_-r_ALTMAP_- 2700.11 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_ALTMAP_- 2367.78 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_SSE_-r_ALTMAP_-d_MATRIX_- 2365.21 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_ALTMAP_-d_EUCLID_- 2364.95 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_SSE_-r_ALTMAP_- 2356.81 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_SSE_-r_ALTMAP_-d_EUCLID_- 2319.16 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_ALTMAP_-d_MATRIX_- 2307.02 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_SSE_-d_EUCLID_- 1879.46 +_12_3_16_128_65536_- 1877.06 +_12_3_16_128_65536_-m_SPLIT_16_4_-d_MATRIX_- 1868.61 +_12_3_16_128_65536_-m_SPLIT_16_4_- 1864.30 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_SSE_-d_MATRIX_- 1861.95 +_12_3_16_128_65536_-m_SPLIT_16_4_-d_EUCLID_- 1854.40 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_SSE_- 1850.96 +_12_3_32_128_65536_-m_COMPOSITE_2_-_-r_ALTMAP_- 1828.50 +_12_3_8_128_65536_-m_TABLE_-r_CAUCHY_- 1534.09 +_12_3_8_128_65536_-m_SPLIT_8_4_-r_CAUCHY_-d_MATRIX_- 1531.78 +_12_3_8_128_65536_-m_LOG_ZERO_EXT_-r_CAUCHY_-d_EUCLID_- 1526.97 +_12_3_8_128_65536_-m_TABLE_-r_CAUCHY_-d_EUCLID_- 1527.21 +_12_3_8_128_65536_-m_LOG_-r_CAUCHY_- 1524.65 +_12_3_8_128_65536_-m_SHIFT_-r_CAUCHY_-d_MATRIX_- 1525.47 +_12_3_8_128_65536_-m_BYTWO_b_-r_CAUCHY_-d_EUCLID_- 1525.53 +_12_3_8_128_65536_-m_LOG_ZERO_EXT_-r_CAUCHY_- 1522.80 +_12_3_8_128_65536_-m_LOG_ZERO_-r_CAUCHY_-d_EUCLID_- 1522.57 +_12_3_8_128_65536_-m_BYTWO_p_-r_CAUCHY_-d_EUCLID_- 1519.20 +_12_3_8_128_65536_-m_BYTWO_p_-r_CAUCHY_-d_MATRIX_- 1517.28 +_12_3_8_128_65536_-m_LOG_-r_CAUCHY_-d_MATRIX_- 1515.57 +_12_3_8_128_65536_-m_TABLE_-r_CAUCHY_-d_MATRIX_- 1516.30 +_12_3_8_128_65536_-m_LOG_ZERO_-r_CAUCHY_- 1516.35 +_12_3_8_128_65536_-m_LOG_ZERO_-r_CAUCHY_-d_MATRIX_- 1515.13 +_12_3_8_128_65536_-m_SHIFT_-r_CAUCHY_-d_EUCLID_- 1513.07 +_12_3_8_128_65536_-m_LOG_ZERO_EXT_-r_CAUCHY_-d_MATRIX_- 1512.42 +_12_3_8_128_65536_-m_LOG_-r_CAUCHY_-d_EUCLID_- 1510.87 +_12_3_8_128_65536_-m_BYTWO_p_-r_CAUCHY_- 1511.34 +_12_3_8_128_65536_-m_BYTWO_b_-r_CAUCHY_- 1508.70 +_12_3_8_128_65536_-m_SPLIT_8_4_-r_CAUCHY_- 1508.28 +_12_3_8_128_65536_-m_SHIFT_-r_CAUCHY_- 1504.25 +_12_3_8_128_65536_-m_SPLIT_8_4_-r_CAUCHY_-d_EUCLID_- 1499.62 +_12_3_8_128_65536_-m_BYTWO_b_-r_CAUCHY_-d_MATRIX_- 1488.90 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_SSE_- 1337.74 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_SSE_-d_EUCLID_- 1334.65 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_SSE_-d_MATRIX_- 1326.72 +_12_3_32_128_65536_-m_SPLIT_32_4_-d_MATRIX_- 1325.45 +_12_3_32_128_65536_- 1325.80 +_12_3_32_128_65536_-m_SPLIT_32_4_-d_EUCLID_- 1325.00 +_12_3_32_128_65536_-m_SPLIT_32_4_- 1300.37 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_ALTMAP_-d_MATRIX_- 1196.01 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_ALTMAP_- 1196.97 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_ALTMAP_-d_EUCLID_- 1193.25 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_SSE_-r_ALTMAP_- 1191.37 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_SSE_-r_ALTMAP_-d_EUCLID_- 1188.98 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_SSE_-r_ALTMAP_-d_MATRIX_- 1187.58 +_12_3_8_128_65536_-m_TABLE_-r_DOUBLE_- 1015.70 +_12_3_8_128_65536_-m_TABLE_-r_DOUBLE_-d_EUCLID_- 999.25 +_12_3_8_128_65536_-m_TABLE_-r_DOUBLE_-d_MATRIX_- 996.35 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_CAUCHY_-d_EUCLID_- 971.19 +_12_3_16_128_65536_-m_LOG_-r_CAUCHY_-d_MATRIX_- 972.08 +_12_3_16_128_65536_-m_LOG_ZERO_-r_CAUCHY_- 967.87 +_12_3_16_128_65536_-m_LOG_ZERO_-r_CAUCHY_-d_EUCLID_- 965.51 +_12_3_16_128_65536_-m_SPLIT_16_8_-r_CAUCHY_-d_MATRIX_- 965.75 +_12_3_16_128_65536_-m_LOG_ZERO_-r_CAUCHY_-d_MATRIX_- 965.41 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_CAUCHY_- 966.20 +_12_3_16_128_65536_-m_SPLIT_16_8_-r_CAUCHY_-d_EUCLID_- 964.21 +_12_3_16_128_65536_-m_LOG_-r_CAUCHY_- 962.11 +_12_3_16_128_65536_-m_SPLIT_8_8_-r_CAUCHY_-d_MATRIX_- 959.53 +_12_3_16_128_65536_-m_LOG_-r_CAUCHY_-d_EUCLID_- 959.75 +_12_3_16_128_65536_-m_SPLIT_16_8_-r_CAUCHY_- 958.98 +_12_3_16_128_65536_-m_BYTWO_p_-r_CAUCHY_-d_MATRIX_- 957.03 +_12_3_16_128_65536_-m_BYTWO_b_-r_CAUCHY_-d_MATRIX_- 955.82 +_12_3_16_128_65536_-m_GROUP_4_4_-r_CAUCHY_-d_EUCLID_- 956.46 +_12_3_16_128_65536_-m_GROUP_4_4_-r_CAUCHY_- 955.41 +_12_3_16_128_65536_-m_GROUP_4_4_-r_CAUCHY_-d_MATRIX_- 955.45 +_12_3_16_128_65536_-m_SPLIT_8_8_-r_CAUCHY_-d_EUCLID_- 955.93 +_12_3_16_128_65536_-m_BYTWO_p_-r_CAUCHY_-d_EUCLID_- 952.43 +_12_3_16_128_65536_-m_BYTWO_b_-r_CAUCHY_-d_EUCLID_- 951.90 +_12_3_16_128_65536_-m_BYTWO_p_-r_CAUCHY_- 945.16 +_12_3_16_128_65536_-m_BYTWO_b_-r_CAUCHY_- 945.30 +_12_3_16_128_65536_-m_SHIFT_-r_CAUCHY_- 944.22 +_12_3_16_128_65536_-m_SHIFT_-r_CAUCHY_-d_MATRIX_- 939.66 +_12_3_16_128_65536_-m_SHIFT_-r_CAUCHY_-d_EUCLID_- 934.56 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_CAUCHY_-d_MATRIX_- 917.26 +_12_3_16_128_65536_-m_SPLIT_8_8_-r_CAUCHY_- 831.63 +_12_3_16_128_65536_-m_SPLIT_16_8_- 621.13 +_12_3_16_128_65536_-m_SPLIT_16_8_-d_MATRIX_- 619.98 +_12_3_16_128_65536_-m_SPLIT_8_8_- 614.67 +_12_3_16_128_65536_-m_SPLIT_16_8_-d_EUCLID_- 603.05 +_12_3_16_128_65536_-m_SPLIT_8_8_-d_MATRIX_- 553.45 +_12_3_16_128_65536_-m_SPLIT_8_8_-d_EUCLID_- 543.90 +_12_3_8_128_65536_-m_BYTWO_b_-d_EUCLID_- 522.34 +_12_3_8_128_65536_-m_BYTWO_b_-r_SSE_- 520.97 +_12_3_8_128_65536_-m_BYTWO_b_-r_SSE_-d_MATRIX_- 520.49 +_12_3_8_128_65536_-m_BYTWO_b_-d_MATRIX_- 518.74 +_12_3_8_128_65536_-m_BYTWO_b_-r_SSE_-d_EUCLID_- 518.95 +_12_3_8_128_65536_-m_BYTWO_b_- 519.19 +_12_3_16_128_65536_-m_LOG_-d_MATRIX_- 485.44 +_12_3_16_128_65536_-m_LOG_- 483.58 +_12_3_16_128_65536_-m_LOG_-d_EUCLID_- 480.18 +_12_3_16_128_65536_-m_LOG_ZERO_-d_EUCLID_- 441.75 +_12_3_16_128_65536_-m_LOG_ZERO_-d_MATRIX_- 427.39 +_12_3_16_128_65536_-m_LOG_ZERO_- 419.07 +_12_3_32_128_65536_-m_SPLIT_8_8_-d_EUCLID_- 415.80 +_12_3_32_128_65536_-m_SPLIT_8_8_- 415.31 +_12_3_32_128_65536_-m_SPLIT_32_8_-d_EUCLID_- 416.06 +_12_3_32_128_65536_-m_BYTWO_p_-r_CAUCHY_-d_EUCLID_- 415.84 +_12_3_8_128_65536_-m_BYTWO_p_-d_MATRIX_- 416.50 +_12_3_8_128_65536_-m_BYTWO_p_- 416.57 +_12_3_32_128_65536_-m_SPLIT_32_8_- 416.36 +_12_3_8_128_65536_-m_BYTWO_p_-r_SSE_- 414.77 +_12_3_8_128_65536_-m_BYTWO_p_-r_SSE_-d_EUCLID_- 414.64 +_12_3_32_128_65536_-m_BYTWO_b_-r_CAUCHY_-d_EUCLID_- 415.14 +_12_3_32_128_65536_-m_BYTWO_b_-r_CAUCHY_- 413.58 +_12_3_32_128_65536_-m_GROUP_4_8_-r_CAUCHY_-d_EUCLID_- 413.55 +_12_3_32_128_65536_-m_SPLIT_8_8_-r_CAUCHY_-d_EUCLID_- 413.76 +_12_3_32_128_65536_-m_SPLIT_32_8_-d_MATRIX_- 413.83 +_12_3_32_128_65536_-m_BYTWO_p_-r_CAUCHY_-d_MATRIX_- 412.09 +_12_3_32_128_65536_-m_SPLIT_32_16_-r_CAUCHY_- 413.06 +_12_3_32_128_65536_-m_GROUP_4_4_-r_CAUCHY_-d_EUCLID_- 413.62 +_12_3_32_128_65536_-m_SPLIT_8_8_-r_CAUCHY_-d_MATRIX_- 411.67 +_12_3_32_128_65536_-m_GROUP_4_4_-r_CAUCHY_- 412.35 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_CAUCHY_-d_MATRIX_- 412.30 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_CAUCHY_-d_EUCLID_- 411.08 +_12_3_32_128_65536_-m_BYTWO_p_-r_CAUCHY_- 411.89 +_12_3_32_128_65536_-m_SPLIT_8_8_-r_CAUCHY_- 412.23 +_12_3_8_128_65536_-m_BYTWO_p_-r_SSE_-d_MATRIX_- 413.10 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_CAUCHY_- 411.24 +_12_3_32_128_65536_-m_SPLIT_32_16_-r_CAUCHY_-d_EUCLID_- 411.23 +_12_3_32_128_65536_-m_SPLIT_32_16_-r_CAUCHY_-d_MATRIX_- 411.49 +_12_3_32_128_65536_-m_GROUP_4_4_-r_CAUCHY_-d_MATRIX_- 410.80 +_12_3_32_128_65536_-m_SPLIT_32_8_-r_CAUCHY_-d_EUCLID_- 409.80 +_12_3_32_128_65536_-m_SPLIT_32_8_-r_CAUCHY_- 408.72 +_12_3_32_128_65536_-m_SPLIT_32_8_-r_CAUCHY_-d_MATRIX_- 409.51 +_12_3_32_128_65536_-m_GROUP_4_8_-r_CAUCHY_- 409.34 +_12_3_8_128_65536_-m_BYTWO_p_-d_EUCLID_- 405.75 +_12_3_32_128_65536_-m_BYTWO_b_-r_CAUCHY_-d_MATRIX_- 406.53 +_12_3_32_128_65536_-m_SPLIT_8_8_-d_MATRIX_- 405.91 +_12_3_32_128_65536_-m_SHIFT_-r_CAUCHY_- 403.98 +_12_3_32_128_65536_-m_SHIFT_-r_CAUCHY_-d_EUCLID_- 404.79 +_12_3_32_128_65536_-m_SHIFT_-r_CAUCHY_-d_MATRIX_- 401.29 +_12_3_8_128_65536_-m_TABLE_-r_DOUBLE_-r_LAZY_-d_EUCLID_- 384.38 +_12_3_8_128_65536_-m_TABLE_-r_DOUBLE_-r_LAZY_- 381.47 +_12_3_8_128_65536_-m_TABLE_-r_DOUBLE_-r_LAZY_-d_MATRIX_- 381.49 +_12_3_32_128_65536_-m_GROUP_4_8_-r_CAUCHY_-d_MATRIX_- 374.88 +_12_3_8_128_65536_-m_LOG_ZERO_-d_MATRIX_- 349.17 +_12_3_8_128_65536_-m_LOG_ZERO_- 349.34 +_12_3_8_128_65536_-m_LOG_ZERO_EXT_-d_MATRIX_- 349.43 +_12_3_8_128_65536_-m_LOG_ZERO_-d_EUCLID_- 349.61 +_12_3_8_128_65536_-m_LOG_ZERO_EXT_- 349.71 +_12_3_8_128_65536_-m_TABLE_-d_EUCLID_- 343.28 +_12_3_8_128_65536_-m_LOG_ZERO_EXT_-d_EUCLID_- 341.73 +_12_3_8_128_65536_-m_TABLE_-d_MATRIX_- 329.42 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_NOSSE_- 327.32 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_NOSSE_-d_EUCLID_- 318.34 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_NOSSE_-d_MATRIX_- 317.40 +_12_3_8_128_65536_-m_TABLE_- 316.84 +_12_3_32_128_65536_-m_COMPOSITE_2_-_- 301.69 +_12_3_8_128_65536_-m_LOG_-d_MATRIX_- 281.59 +_12_3_8_128_65536_-m_LOG_-d_EUCLID_- 281.28 +_12_3_8_128_65536_-m_LOG_- 279.75 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_NOSSE_-r_ALTMAP_- 275.37 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_NOSSE_-r_ALTMAP_-d_EUCLID_- 276.07 +_12_3_16_128_65536_-m_SPLIT_16_4_-r_NOSSE_-r_ALTMAP_-d_MATRIX_- 269.77 +_12_3_8_128_65536_-m_BYTWO_b_-r_NOSSE_-d_MATRIX_- 257.86 +_12_3_8_128_65536_-m_BYTWO_b_-r_NOSSE_-d_EUCLID_- 256.55 +_12_3_8_128_65536_-m_SPLIT_8_4_-r_NOSSE_-d_EUCLID_- 236.07 +_12_3_8_128_65536_-m_SPLIT_8_4_-r_NOSSE_-d_MATRIX_- 236.76 +_12_3_8_128_65536_-m_SPLIT_8_4_-r_NOSSE_- 236.71 +_12_3_16_128_65536_-m_BYTWO_b_-d_EUCLID_- 217.68 +_12_3_16_128_65536_-m_BYTWO_b_- 217.87 +_12_3_16_128_65536_-m_BYTWO_b_-r_SSE_- 217.10 +_12_3_16_128_65536_-m_BYTWO_b_-r_SSE_-d_MATRIX_- 216.91 +_12_3_16_128_65536_-m_BYTWO_b_-r_SSE_-d_EUCLID_- 217.27 +_12_3_16_128_65536_-m_BYTWO_b_-d_MATRIX_- 215.01 +_12_3_8_128_65536_-m_BYTWO_p_-r_NOSSE_- 206.00 +_12_3_8_128_65536_-m_BYTWO_p_-r_NOSSE_-d_MATRIX_- 205.66 +_12_3_8_128_65536_-m_BYTWO_p_-r_NOSSE_-d_EUCLID_- 204.44 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_NOSSE_-d_MATRIX_- 199.64 +_12_3_32_128_65536_-m_SPLIT_32_4_-r_NOSSE_-d_EUCLID_- 198.20 +_12_3_16_128_65536_-m_COMPOSITE_2_-_- 182.98 +_12_3_16_128_65536_-m_BYTWO_p_-r_SSE_- 183.34 +_12_3_16_128_65536_-m_BYTWO_p_-r_SSE_-d_EUCLID_- 182.87 +_12_3_16_128_65536_-m_BYTWO_p_-d_EUCLID_- 183.57 +_12_3_16_128_65536_-m_BYTWO_p_-d_MATRIX_- 183.95 +_12_3_16_128_65536_-m_BYTWO_p_-r_SSE_-d_MATRIX_- 179.94 +_12_3_16_128_65536_-m_GROUP_4_4_- 166.90 +_12_3_32_128_65536_-m_SPLIT_32_16_- 167.55 +_12_3_32_128_65536_-m_SPLIT_32_16_-d_MATRIX_- 167.51 +_12_3_32_128_65536_-m_SPLIT_32_16_-d_EUCLID_- 167.70 +_12_3_16_128_65536_-m_GROUP_4_4_-d_EUCLID_- 166.56 +_12_3_16_128_65536_-m_GROUP_4_4_-d_MATRIX_- 167.07 +_12_3_16_128_65536_-m_BYTWO_b_-r_NOSSE_-d_EUCLID_- 110.64 +_12_3_16_128_65536_-m_BYTWO_b_-r_NOSSE_- 110.76 +_12_3_16_128_65536_-m_BYTWO_b_-r_NOSSE_-d_MATRIX_- 111.17 +_12_3_16_128_65536_-m_BYTWO_p_-r_NOSSE_- 100.39 +_12_3_16_128_65536_-m_BYTWO_p_-r_NOSSE_-d_EUCLID_- 100.27 +_12_3_16_128_65536_-m_BYTWO_p_-r_NOSSE_-d_MATRIX_- 100.18 +_12_3_32_128_65536_-m_BYTWO_b_-r_SSE_- 96.85 +_12_3_32_128_65536_-m_BYTWO_b_-d_MATRIX_- 97.76 +_12_3_32_128_65536_-m_BYTWO_b_-r_SSE_-d_EUCLID_- 97.69 +_12_3_32_128_65536_-m_BYTWO_b_-r_SSE_-d_MATRIX_- 97.48 +_12_3_32_128_65536_-m_BYTWO_b_-d_EUCLID_- 97.42 +_12_3_32_128_65536_-m_BYTWO_b_- 97.54 +_12_3_32_128_65536_-m_BYTWO_p_- 86.61 +_12_3_32_128_65536_-m_BYTWO_p_-d_MATRIX_- 86.81 +_12_3_32_128_65536_-m_BYTWO_p_-r_SSE_-d_MATRIX_- 86.31 +_12_3_32_128_65536_-m_BYTWO_p_-d_EUCLID_- 86.70 +_12_3_32_128_65536_-m_BYTWO_p_-r_SSE_- 86.69 +_12_3_32_128_65536_-m_BYTWO_p_-r_SSE_-d_EUCLID_- 86.80 +_12_3_8_128_65536_-m_COMPOSITE_2_-_- 76.58 +_12_3_32_128_65536_-m_GROUP_4_8_-d_EUCLID_- 57.06 +_12_3_32_128_65536_-m_GROUP_4_8_-d_MATRIX_- 57.08 +_12_3_32_128_65536_-m_GROUP_4_4_-d_EUCLID_- 56.59 +_12_3_32_128_65536_-m_GROUP_4_4_-d_MATRIX_- 56.91 +_12_3_32_128_65536_-m_GROUP_4_8_- 54.68 +_12_3_32_128_65536_-m_BYTWO_b_-r_NOSSE_-d_EUCLID_- 50.64 +_12_3_32_128_65536_-m_BYTWO_b_-r_NOSSE_-d_MATRIX_- 50.55 +_12_3_32_128_65536_-m_BYTWO_b_-r_NOSSE_- 50.75 +_12_3_32_128_65536_-m_BYTWO_p_-r_NOSSE_-d_EUCLID_- 49.50 +_12_3_32_128_65536_-m_BYTWO_p_-r_NOSSE_- 49.14 +_12_3_32_128_65536_-m_BYTWO_p_-r_NOSSE_-d_MATRIX_- 47.39 +_12_3_8_128_65536_-m_SHIFT_-d_EUCLID_- 14.08 +_12_3_8_128_65536_-m_SHIFT_-d_MATRIX_- 14.39 +_12_3_8_128_65536_-m_SHIFT_- 14.48 +_12_3_16_128_65536_-m_SHIFT_-d_EUCLID_- 12.75 +_12_3_16_128_65536_-m_SHIFT_-d_MATRIX_- 12.74 +_12_3_16_128_65536_-m_SHIFT_- 12.77 +_12_3_32_128_65536_-m_SHIFT_-d_MATRIX_- 12.51 +_12_3_32_128_65536_-m_SHIFT_-d_EUCLID_- 12.50 +_12_3_32_128_65536_-m_SHIFT_- 12.46 diff --git a/README b/README new file mode 100644 index 0000000..699a60a --- /dev/null +++ b/README @@ -0,0 +1,95 @@ +This is revision 2.0 of Jerasure. This is pretty much Jerasure 1.2 without the +original Galois Field backend. Version 2.0 links directly to GF-Complete, which +is more flexible than the original, and *much* faster, because it leverages SIMD +instructions. +Authors: James S. Plank (University of Tennessee) + Kevin M. Greenan (Box) + +------------------------------------------------------------ + +The online home for jerasure is: + + - http://jerasure.org/jerasure/jerasure + +------------------------------------------------------------ + +External Documentation: + +See the file Manual.pdf for the programmer's manual and tutorial. + +See http://jerasure.org/jerasure/gf-complete for GF-Complete. + +NOTE: You must have GF-Complete installed (or compiled) in order to use Jerasure 2.0. + +There are two directories of source code: + +The src directory contains the jerasure code. +The Examples directory contains the example programs. + +------------------------------------------------------------ + +If you do not have Autoconf 2.65 or later installed, you can simply build +from the tarball distribution: + +http://www.kaymgee.com/Kevin_Greenan/Software_files/jerasure.tar.gz + +Installing if you are allowed to install GF-Complete on your machine: +(You can skip the autoreconf step if you're using a tarball distribution.) + +1.) Install GF-Complete +2.) autoreconf --force --install (*skip* if you are building from tarball) +3.) ./configure +4.) make +5.) sudo make install + +This will install the library into your machine's lib directory, +the headers into include, and the example programs into bin. + +The configuration process assumes shared objects are searched for in +/usr/local/lib. If this is not the case on your system, you can specify a +search path at configuration time. For example: + ./configure LD_LIBRARY_PATH=/usr/local/lib + +------------------------------------------------------------ + +Installing if you can compile GF-Complete, but you cannot install it: + +1.) Install GF-Complete. Let's suppose the full path to GF-Complete is + in the environment variable GFP +2A.) On Linux, set the environment variable LD_LIBRARY_PATH so that it + includes $GFP/src/.libs +2B.) On a mac, set the environment variable DYLD_LIBRARY_PATH so that it + includes $GFP/src/.libs +2.) ./configure LDFLAGS=-L$GFP/src/.libs/ CPPFLAGS=-I$GFP/include +3.) make + +The examples will be in the directory Examples. The include files will +be in the directory include, and the library will be called libJerasure.a +in the directory src/.libs. + +------------------------------------------------------------ + +As long as GF-Complete is installed, Jerasure 2.0 can be used just as previous +versions. There is no need to define custom Galois Fields. Jerasure will +determine the default field to use, if one is not specified. + +If you would like to explore a using a different Galois Field implementation, +please see the manual. + +------------------------------------------------------------ + +Testing GF-Complete + +If the GF-Complete tools are installed in /usr/local/bin + + make check + +If the GF-Complete tools are installed elsewhere + + make GF_COMPLETE_DIR=$(pwd)/../gf-complete/tools check + +To run some tests with valgrind + + make VALGRIND='valgrind --tool=memcheck --quiet' \ + GF_COMPLETE_DIR=$(pwd)/../gf-complete/tools \ + check diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..63e6b0e --- /dev/null +++ b/configure.ac @@ -0,0 +1,54 @@ +# Jerasure autoconf template + +AC_PREREQ([2.65]) +AC_INIT([Jerasure], [2.0], [], [], + [https://jerasure.org/jerasure/jerasure]) +AC_CONFIG_SRCDIR([src/jerasure.c]) +AC_CONFIG_HEADERS([include/config.h]) + +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIR([m4]) + +AM_INIT_AUTOMAKE([1.13 -Wall -Wno-extra-portability]) + +# Package default C compiler flags. +dnl This must be before LT_INIT and AC_PROG_CC. +: ${CFLAGS='-g -O3 -Wall'} + +LT_INIT([disable-static]) + +# Checks for programs. +AC_PROG_CC + +# Checks for libraries. +AC_CHECK_LIB([gf_complete], [gf_init_easy], [], + [AC_MSG_FAILURE( + [You need to have gf_complete installed. + gf_complete is available from http://jerasure.org/jerasure/gf-complete]) + ]) + +# Checks for header files. +AC_CHECK_HEADERS([stddef.h stdint.h stdlib.h string.h sys/time.h unistd.h]) +AC_CHECK_HEADERS([gf_complete.h gf_general.h gf_method.h gf_rand.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_UINT32_T +AC_TYPE_UINT64_T +AX_EXT + +AC_ARG_ENABLE([sse], + AS_HELP_STRING([--disable-sse], [Build without SSE optimizations]), + [if test "x$enableval" = "xno" ; then + SIMD_FLAGS="" + echo "DISABLED SSE!!!" + fi] +) + +# Checks for library functions. +AC_FUNC_MALLOC +AC_CHECK_FUNCS([bzero getcwd gettimeofday mkdir strchr strdup strrchr]) + +AC_CONFIG_FILES([Examples/Makefile + Makefile + src/Makefile]) +AC_OUTPUT diff --git a/include/cauchy.h b/include/cauchy.h new file mode 100644 index 0000000..f8d1ae3 --- /dev/null +++ b/include/cauchy.h @@ -0,0 +1,54 @@ +/* * + * Copyright (c) 2013, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +extern int *cauchy_original_coding_matrix(int k, int m, int w); +extern int *cauchy_xy_coding_matrix(int k, int m, int w, int *x, int *y); +extern void cauchy_improve_coding_matrix(int k, int m, int w, int *matrix); +extern int *cauchy_good_general_coding_matrix(int k, int m, int w); +extern int cauchy_n_ones(int n, int w); + +#ifdef __cplusplus +} +#endif diff --git a/include/galois.h b/include/galois.h new file mode 100644 index 0000000..78e6567 --- /dev/null +++ b/include/galois.h @@ -0,0 +1,103 @@ +/* * + * Copyright (c) 2013, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int galois_init_default_field(int w); +extern int galois_uninit_field(int w); +extern void galois_change_technique(gf_t *gf, int w); + +extern int galois_single_multiply(int a, int b, int w); +extern int galois_single_divide(int a, int b, int w); +extern int galois_inverse(int x, int w); + +void galois_region_xor( char *src, /* Source Region */ + char *dest, /* Dest Region (holds result) */ + int nbytes); /* Number of bytes in region */ + +/* These multiply regions in w=8, w=16 and w=32. They are much faster + than calling galois_single_multiply. The regions must be long word aligned. */ + +void galois_w08_region_multiply(char *region, /* Region to multiply */ + int multby, /* Number to multiply by */ + int nbytes, /* Number of bytes in region */ + char *r2, /* If r2 != NULL, products go here. + Otherwise region is overwritten */ + int add); /* If (r2 != NULL && add) the produce is XOR'd with r2 */ + +void galois_w16_region_multiply(char *region, /* Region to multiply */ + int multby, /* Number to multiply by */ + int nbytes, /* Number of bytes in region */ + char *r2, /* If r2 != NULL, products go here. + Otherwise region is overwritten */ + int add); /* If (r2 != NULL && add) the produce is XOR'd with r2 */ + +void galois_w32_region_multiply(char *region, /* Region to multiply */ + int multby, /* Number to multiply by */ + int nbytes, /* Number of bytes in region */ + char *r2, /* If r2 != NULL, products go here. + Otherwise region is overwritten */ + int add); /* If (r2 != NULL && add) the produce is XOR'd with r2 */ + +gf_t* galois_init_field(int w, + int mult_type, + int region_type, + int divide_type, + uint64_t prim_poly, + int arg1, + int arg2); + +gf_t* galois_init_composite_field(int w, + int region_type, + int divide_type, + int degree, + gf_t* base_gf); + +gf_t * galois_get_field_ptr(int w); + +#ifdef __cplusplus +} +#endif diff --git a/include/jerasure.h b/include/jerasure.h new file mode 100644 index 0000000..de874e1 --- /dev/null +++ b/include/jerasure.h @@ -0,0 +1,302 @@ +/* * + * Copyright (c) 2013, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#ifndef _JERASURE_H +#define _JERASURE_H + +/* This uses procedures from the Galois Field arithmetic library */ + +#include "galois.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------------------------------------------------ */ +/* In all of the routines below: + + k = Number of data devices + m = Number of coding devices + w = Word size + + data_ptrs = An array of k pointers to data which is size bytes. + Size must be a multiple of sizeof(long). + Pointers must also be longword aligned. + + coding_ptrs = An array of m pointers to coding data which is size bytes. + + packetsize = The size of a coding block with bitmatrix coding. + When you code with a bitmatrix, you will use w packets + of size packetsize. + + matrix = an array of k*m integers. + It represents an m by k matrix. + Element i,j is in matrix[i*k+j]; + + bitmatrix = an array of k*m*w*w integers. + It represents an mw by kw matrix. + Element i,j is in matrix[i*k*w+j]; + + erasures = an array of id's of erased devices. + Id's are integers between 0 and k+m-1. + Id's 0 to k-1 are id's of data devices. + Id's k to k+m-1 are id's of coding devices: + Coding device id = id-k. + If there are e erasures, erasures[e] = -1. + + schedule = an array of schedule operations. + + If there are m operations, then schedule[m][0] = -1. + + operation = an array of 5 integers: + + 0 = operation: 0 for copy, 1 for xor (-1 for end) + 1 = source device (0 - k+m-1) + 2 = source packet (0 - w-1) + 3 = destination device (0 - k+m-1) + 4 = destination packet (0 - w-1) + */ + +/* --------------------------------------------------------------- */ +/* Bitmatrices / schedules ---------------------------------------- */ +/* + - jerasure_matrix_to_bitmatrix turns a m X k matrix in GF(2^w) into a + wm X wk bitmatrix (in GF(2)). This is + explained in the Cauchy Reed-Solomon coding + paper. + + - jerasure_dumb_bitmatrix_to_schedule turns a bitmatrix into a schedule + using the straightforward algorithm -- just + schedule the dot products defined by each + row of the matrix. + + - jerasure_smart_bitmatrix_to_schedule turns a bitmatrix into a schedule, + but tries to use previous dot products to + calculate new ones. This is the optimization + explained in the original Liberation code paper. + + - jerasure_generate_schedule_cache precalcalculate all the schedule for the + given distribution bitmatrix. M must equal 2. + + - jerasure_free_schedule frees a schedule that was allocated with + jerasure_XXX_bitmatrix_to_schedule. + + - jerasure_free_schedule_cache frees a schedule cache that was created with + jerasure_generate_schedule_cache. + */ + +int *jerasure_matrix_to_bitmatrix(int k, int m, int w, int *matrix); +int **jerasure_dumb_bitmatrix_to_schedule(int k, int m, int w, int *bitmatrix); +int **jerasure_smart_bitmatrix_to_schedule(int k, int m, int w, int *bitmatrix); +int ***jerasure_generate_schedule_cache(int k, int m, int w, int *bitmatrix, int smart); + +void jerasure_free_schedule(int **schedule); +void jerasure_free_schedule_cache(int k, int m, int ***cache); + + +/* ------------------------------------------------------------ */ +/* Encoding - these are all straightforward. jerasure_matrix_encode only + works with w = 8|16|32. */ + +void jerasure_do_parity(int k, char **data_ptrs, char *parity_ptr, int size); + +void jerasure_matrix_encode(int k, int m, int w, int *matrix, + char **data_ptrs, char **coding_ptrs, int size); + +void jerasure_bitmatrix_encode(int k, int m, int w, int *bitmatrix, + char **data_ptrs, char **coding_ptrs, int size, int packetsize); + +void jerasure_schedule_encode(int k, int m, int w, int **schedule, + char **data_ptrs, char **coding_ptrs, int size, int packetsize); + +/* ------------------------------------------------------------ */ +/* Decoding. -------------------------------------------------- */ + +/* These return integers, because the matrix may not be invertible. + + The parameter row_k_ones should be set to 1 if row k of the matrix + (or rows kw to (k+1)w+1) of th distribution matrix are all ones + (or all identity matrices). Then you can improve the performance + of decoding when there is more than one failure, and the parity + device didn't fail. You do it by decoding all but one of the data + devices, and then decoding the last data device from the data devices + and the parity device. + + jerasure_schedule_decode_lazy generates the schedule on the fly. + + jerasure_matrix_decode only works when w = 8|16|32. + + jerasure_make_decoding_matrix/bitmatrix make the k*k decoding matrix + (or wk*wk bitmatrix) by taking the rows corresponding to k + non-erased devices of the distribution matrix, and then + inverting that matrix. + + You should already have allocated the decoding matrix and + dm_ids, which is a vector of k integers. These will be + filled in appropriately. dm_ids[i] is the id of element + i of the survivors vector. I.e. row i of the decoding matrix + times dm_ids equals data drive i. + + Both of these routines take "erased" instead of "erasures". + Erased is a vector with k+m elements, which has 0 or 1 for + each device's id, according to whether the device is erased. + + jerasure_erasures_to_erased allocates and returns erased from erasures. + + */ + +int jerasure_matrix_decode(int k, int m, int w, + int *matrix, int row_k_ones, int *erasures, + char **data_ptrs, char **coding_ptrs, int size); + +int jerasure_bitmatrix_decode(int k, int m, int w, + int *bitmatrix, int row_k_ones, int *erasures, + char **data_ptrs, char **coding_ptrs, int size, int packetsize); + +int jerasure_schedule_decode_lazy(int k, int m, int w, int *bitmatrix, int *erasures, + char **data_ptrs, char **coding_ptrs, int size, int packetsize, + int smart); + +int jerasure_schedule_decode_cache(int k, int m, int w, int ***scache, int *erasures, + char **data_ptrs, char **coding_ptrs, int size, int packetsize); + +int jerasure_make_decoding_matrix(int k, int m, int w, int *matrix, int *erased, + int *decoding_matrix, int *dm_ids); + +int jerasure_make_decoding_bitmatrix(int k, int m, int w, int *matrix, int *erased, + int *decoding_matrix, int *dm_ids); + +int *jerasure_erasures_to_erased(int k, int m, int *erasures); + +/* ------------------------------------------------------------ */ +/* These perform dot products and schedules. -------------------*/ +/* + src_ids is a matrix of k id's (0 - k-1 for data devices, k - k+m-1 + for coding devices) that identify the source devices. Dest_id is + the id of the destination device. + + jerasure_matrix_dotprod only works when w = 8|16|32. + + jerasure_do_scheduled_operations executes the schedule on w*packetsize worth of + bytes from each device. ptrs is an array of pointers which should have as many + elements as the highest referenced device in the schedule. + + */ + +void jerasure_matrix_dotprod(int k, int w, int *matrix_row, + int *src_ids, int dest_id, + char **data_ptrs, char **coding_ptrs, int size); + +void jerasure_bitmatrix_dotprod(int k, int w, int *bitmatrix_row, + int *src_ids, int dest_id, + char **data_ptrs, char **coding_ptrs, int size, int packetsize); + +void jerasure_do_scheduled_operations(char **ptrs, int **schedule, int packetsize); + +/* ------------------------------------------------------------ */ +/* Matrix Inversion ------------------------------------------- */ +/* + The two matrix inversion functions work on rows*rows matrices of + ints. If a bitmatrix, then each int will just be zero or one. + Otherwise, they will be elements of gf(2^w). Obviously, you can + do bit matrices with crs_invert_matrix() and set w = 1, but + crs_invert_bitmatrix will be more efficient. + + The two invertible functions return whether a matrix is invertible. + They are more efficient than the inverstion functions. + + Mat will be destroyed when the matrix inversion or invertible + testing is done. Sorry. + + Inv must be allocated by the caller. + + The two invert_matrix functions return 0 on success, and -1 if the + matrix is uninvertible. + + The two invertible function simply return whether the matrix is + invertible. (0 or 1). Mat will be destroyed. + */ + +int jerasure_invert_matrix(int *mat, int *inv, int rows, int w); +int jerasure_invert_bitmatrix(int *mat, int *inv, int rows); +int jerasure_invertible_matrix(int *mat, int rows, int w); +int jerasure_invertible_bitmatrix(int *mat, int rows); + +/* ------------------------------------------------------------ */ +/* Basic matrix operations -------------------------------------*/ +/* + Each of the print_matrix routines require a w. In jerasure_print_matrix, + this is to calculate the field width. In jerasure_print_bitmatrix, it is + to put spaces between the bits. + + jerasure_matrix_multiply is a simple matrix multiplier in GF(2^w). It returns a r1*c2 + matrix, which is the product of the two input matrices. It allocates + the product. Obviously, c1 should equal r2. However, this is not + validated by the procedure. +*/ + +void jerasure_print_matrix(int *matrix, int rows, int cols, int w); +void jerasure_print_bitmatrix(int *matrix, int rows, int cols, int w); + + +int *jerasure_matrix_multiply(int *m1, int *m2, int r1, int c1, int r2, int c2, int w); + +/* ------------------------------------------------------------ */ +/* Stats ------------------------------------------------------ */ +/* + jerasure_get_stats fills in a vector of three doubles: + + fill_in[0] is the number of bytes that have been XOR'd + fill_in[1] is the number of bytes that have been copied + fill_in[2] is the number of bytes that have been multiplied + by a constant in GF(2^w) + + When jerasure_get_stats() is called, it resets its values. + */ + +void jerasure_get_stats(double *fill_in); + +int jerasure_autoconf_test(); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/liberation.h b/include/liberation.h new file mode 100644 index 0000000..150acb9 --- /dev/null +++ b/include/liberation.h @@ -0,0 +1,52 @@ +/* * + * Copyright (c) 2013, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +extern int *liberation_coding_bitmatrix(int k, int w); +extern int *liber8tion_coding_bitmatrix(int k); +extern int *blaum_roth_coding_bitmatrix(int k, int w); + +#ifdef __cplusplus +} +#endif diff --git a/include/reed_sol.h b/include/reed_sol.h new file mode 100644 index 0000000..48fc4e6 --- /dev/null +++ b/include/reed_sol.h @@ -0,0 +1,59 @@ +/* * + * Copyright (c) 2013, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +extern int *reed_sol_vandermonde_coding_matrix(int k, int m, int w); +extern int *reed_sol_extended_vandermonde_matrix(int rows, int cols, int w); +extern int *reed_sol_big_vandermonde_distribution_matrix(int rows, int cols, int w); + +extern int reed_sol_r6_encode(int k, int w, char **data_ptrs, char **coding_ptrs, int size); +extern int *reed_sol_r6_coding_matrix(int k, int w); + +extern void reed_sol_galois_w08_region_multby_2(char *region, int nbytes); +extern void reed_sol_galois_w16_region_multby_2(char *region, int nbytes); +extern void reed_sol_galois_w32_region_multby_2(char *region, int nbytes); + +#ifdef __cplusplus +} +#endif diff --git a/include/timing.h b/include/timing.h new file mode 100644 index 0000000..b489d0d --- /dev/null +++ b/include/timing.h @@ -0,0 +1,43 @@ +// Timing measurement utilities. + +#ifndef JERASURE_INCLUDED__TIMING_H +#define JERASURE_INCLUDED__TIMING_H + +// Define USE_CLOCK to use clock(). Otherwise use gettimeofday(). +#define USE_CLOCK + +#ifdef USE_CLOCK +#include +#else +#include +#endif + +struct timing { +#ifdef USE_CLOCK + clock_t clock; +#else + struct timeval tv; +#endif +}; + +// Get the current time as a double in seconds. +double +timing_now( + void); + +// Set *t to the current time. +void +timing_set( + struct timing * t); + +// Get *t as a double in seconds. +double +timing_get( + struct timing * t); + +// Return *t2 - *t1 as a double in seconds. +double +timing_delta( + struct timing * t1, + struct timing * t2); +#endif diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 new file mode 100644 index 0000000..51df0c0 --- /dev/null +++ b/m4/ax_check_compile_flag.m4 @@ -0,0 +1,74 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# 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 3 of the License, 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, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 3 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/m4/ax_ext.m4 b/m4/ax_ext.m4 new file mode 100644 index 0000000..70a83bf --- /dev/null +++ b/m4/ax_ext.m4 @@ -0,0 +1,247 @@ +# +# Modified from autoconf-archive to replace AC_REQUIRE([AX_GCC_X86_*]) with +# AX_REQUIRE_DEFINED(...). +# +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_ext.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_EXT +# +# DESCRIPTION +# +# Find supported SIMD extensions by requesting cpuid. When an SIMD +# extension is found, the -m"simdextensionname" is added to SIMD_FLAGS if +# compiler supports it. For example, if "sse2" is available, then "-msse2" +# is added to SIMD_FLAGS. +# +# This macro calls: +# +# AC_SUBST(SIMD_FLAGS) +# +# And defines: +# +# HAVE_MMX / HAVE_SSE / HAVE_SSE2 / HAVE_SSE3 / HAVE_SSSE3 / HAVE_SSE4.1 / HAVE_SSE4.2 / HAVE_AVX +# +# LICENSE +# +# Copyright (c) 2007 Christophe Tournayre +# Copyright (c) 2013 Michael Petch +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 13.1 + +AC_DEFUN([AX_EXT], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + + case $host_cpu in + powerpc*) + AC_CACHE_CHECK([whether altivec is supported], [ax_cv_have_altivec_ext], + [ + if test `/usr/sbin/sysctl -a 2>/dev/null| grep -c hw.optional.altivec` != 0; then + if test `/usr/sbin/sysctl -n hw.optional.altivec` = 1; then + ax_cv_have_altivec_ext=yes + fi + fi + ]) + + if test "$ax_cv_have_altivec_ext" = yes; then + AC_DEFINE(HAVE_ALTIVEC,,[Support Altivec instructions]) + AX_CHECK_COMPILE_FLAG(-faltivec, SIMD_FLAGS="$SIMD_FLAGS -faltivec", []) + fi + ;; + + + i[[3456]]86*|x86_64*|amd64*) + + AX_REQUIRE_DEFINED([AX_GCC_X86_CPUID]) + AX_REQUIRE_DEFINED([AX_GCC_X86_AVX_XGETBV]) + + AX_GCC_X86_CPUID(0x00000001) + ecx=0 + edx=0 + if test "$ax_cv_gcc_x86_cpuid_0x00000001" != "unknown"; + then + ecx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 3` + edx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 4` + fi + + AC_CACHE_CHECK([whether mmx is supported], [ax_cv_have_mmx_ext], + [ + ax_cv_have_mmx_ext=no + if test "$((0x$edx>>23&0x01))" = 1; then + ax_cv_have_mmx_ext=yes + fi + ]) + + AC_CACHE_CHECK([whether sse is supported], [ax_cv_have_sse_ext], + [ + ax_cv_have_sse_ext=no + if test "$((0x$edx>>25&0x01))" = 1; then + ax_cv_have_sse_ext=yes + fi + ]) + + AC_CACHE_CHECK([whether sse2 is supported], [ax_cv_have_sse2_ext], + [ + ax_cv_have_sse2_ext=no + if test "$((0x$edx>>26&0x01))" = 1; then + ax_cv_have_sse2_ext=yes + fi + ]) + + AC_CACHE_CHECK([whether sse3 is supported], [ax_cv_have_sse3_ext], + [ + ax_cv_have_sse3_ext=no + if test "$((0x$ecx&0x01))" = 1; then + ax_cv_have_sse3_ext=yes + fi + ]) + + AC_CACHE_CHECK([whether ssse3 is supported], [ax_cv_have_ssse3_ext], + [ + ax_cv_have_ssse3_ext=no + if test "$((0x$ecx>>9&0x01))" = 1; then + ax_cv_have_ssse3_ext=yes + fi + ]) + + AC_CACHE_CHECK([whether sse4.1 is supported], [ax_cv_have_sse41_ext], + [ + ax_cv_have_sse41_ext=no + if test "$((0x$ecx>>19&0x01))" = 1; then + ax_cv_have_sse41_ext=yes + fi + ]) + + AC_CACHE_CHECK([whether sse4.2 is supported], [ax_cv_have_sse42_ext], + [ + ax_cv_have_sse42_ext=no + if test "$((0x$ecx>>20&0x01))" = 1; then + ax_cv_have_sse42_ext=yes + fi + ]) + + AC_CACHE_CHECK([whether avx is supported by processor], [ax_cv_have_avx_cpu_ext], + [ + ax_cv_have_avx_cpu_ext=no + if test "$((0x$ecx>>28&0x01))" = 1; then + ax_cv_have_avx_cpu_ext=yes + fi + ]) + + if test x"$ax_cv_have_avx_cpu_ext" = x"yes"; then + AX_GCC_X86_AVX_XGETBV(0x00000000) + + xgetbv_eax="0" + if test x"$ax_cv_gcc_x86_avx_xgetbv_0x00000000" != x"unknown"; then + xgetbv_eax=`echo $ax_cv_gcc_x86_avx_xgetbv_0x00000000 | cut -d ":" -f 1` + fi + + AC_CACHE_CHECK([whether avx is supported by operating system], [ax_cv_have_avx_ext], + [ + ax_cv_have_avx_ext=no + + if test "$((0x$ecx>>27&0x01))" = 1; then + if test "$((0x$xgetbv_eax&0x6))" = 6; then + ax_cv_have_avx_ext=yes + fi + fi + ]) + if test x"$ax_cv_have_avx_ext" = x"no"; then + AC_MSG_WARN([Your processor supports AVX, but your operating system doesn't]) + fi + fi + + if test "$ax_cv_have_mmx_ext" = yes; then + AX_CHECK_COMPILE_FLAG(-mmmx, ax_cv_support_mmx_ext=yes, []) + if test x"$ax_cv_support_mmx_ext" = x"yes"; then + SIMD_FLAGS="$SIMD_FLAGS -mmmx" + AC_DEFINE(HAVE_MMX,,[Support mmx instructions]) + else + AC_MSG_WARN([Your processor supports mmx instructions but not your compiler, can you try another compiler?]) + fi + fi + + if test "$ax_cv_have_sse_ext" = yes; then + AX_CHECK_COMPILE_FLAG(-msse, ax_cv_support_sse_ext=yes, []) + if test x"$ax_cv_support_sse_ext" = x"yes"; then + SIMD_FLAGS="$SIMD_FLAGS -msse" + AC_DEFINE(HAVE_SSE,,[Support SSE (Streaming SIMD Extensions) instructions]) + else + AC_MSG_WARN([Your processor supports sse instructions but not your compiler, can you try another compiler?]) + fi + fi + + if test "$ax_cv_have_sse2_ext" = yes; then + AX_CHECK_COMPILE_FLAG(-msse2, ax_cv_support_sse2_ext=yes, []) + if test x"$ax_cv_support_sse2_ext" = x"yes"; then + SIMD_FLAGS="$SIMD_FLAGS -msse2" + AC_DEFINE(HAVE_SSE2,,[Support SSE2 (Streaming SIMD Extensions 2) instructions]) + else + AC_MSG_WARN([Your processor supports sse2 instructions but not your compiler, can you try another compiler?]) + fi + fi + + if test "$ax_cv_have_sse3_ext" = yes; then + AX_CHECK_COMPILE_FLAG(-msse3, ax_cv_support_sse3_ext=yes, []) + if test x"$ax_cv_support_sse3_ext" = x"yes"; then + SIMD_FLAGS="$SIMD_FLAGS -msse3" + AC_DEFINE(HAVE_SSE3,,[Support SSE3 (Streaming SIMD Extensions 3) instructions]) + else + AC_MSG_WARN([Your processor supports sse3 instructions but not your compiler, can you try another compiler?]) + fi + fi + + if test "$ax_cv_have_ssse3_ext" = yes; then + AX_CHECK_COMPILE_FLAG(-mssse3, ax_cv_support_ssse3_ext=yes, []) + if test x"$ax_cv_support_ssse3_ext" = x"yes"; then + SIMD_FLAGS="$SIMD_FLAGS -mssse3" + AC_DEFINE(HAVE_SSSE3,,[Support SSSE3 (Supplemental Streaming SIMD Extensions 3) instructions]) + else + AC_MSG_WARN([Your processor supports ssse3 instructions but not your compiler, can you try another compiler?]) + fi + fi + + if test "$ax_cv_have_sse41_ext" = yes; then + AX_CHECK_COMPILE_FLAG(-msse4.1, ax_cv_support_sse41_ext=yes, []) + if test x"$ax_cv_support_sse41_ext" = x"yes"; then + SIMD_FLAGS="$SIMD_FLAGS -msse4.1" + AC_DEFINE(HAVE_SSE4_1,,[Support SSSE4.1 (Streaming SIMD Extensions 4.1) instructions]) + else + AC_MSG_WARN([Your processor supports sse4.1 instructions but not your compiler, can you try another compiler?]) + fi + fi + + if test "$ax_cv_have_sse42_ext" = yes; then + AX_CHECK_COMPILE_FLAG(-msse4.2, ax_cv_support_sse42_ext=yes, []) + if test x"$ax_cv_support_sse42_ext" = x"yes"; then + SIMD_FLAGS="$SIMD_FLAGS -msse4.2" + AC_DEFINE(HAVE_SSE4_2,,[Support SSSE4.2 (Streaming SIMD Extensions 4.2) instructions]) + else + AC_MSG_WARN([Your processor supports sse4.2 instructions but not your compiler, can you try another compiler?]) + fi + fi + + if test "$ax_cv_have_avx_ext" = yes; then + AX_CHECK_COMPILE_FLAG(-mavx, ax_cv_support_avx_ext=yes, []) + if test x"$ax_cv_support_avx_ext" = x"yes"; then + SIMD_FLAGS="$SIMD_FLAGS -mavx" + AC_DEFINE(HAVE_AVX,,[Support AVX (Advanced Vector Extensions) instructions]) + else + AC_MSG_WARN([Your processor supports avx instructions but not your compiler, can you try another compiler?]) + fi + fi + + ;; + esac + + AC_SUBST(SIMD_FLAGS) +]) diff --git a/m4/ax_gcc_x86_avx_xgetbv.m4 b/m4/ax_gcc_x86_avx_xgetbv.m4 new file mode 100644 index 0000000..0624eeb --- /dev/null +++ b/m4/ax_gcc_x86_avx_xgetbv.m4 @@ -0,0 +1,79 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_gcc_x86_avx_xgetbv.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_GCC_X86_AVX_XGETBV +# +# DESCRIPTION +# +# On later x86 processors with AVX SIMD support, with gcc or a compiler +# that has a compatible syntax for inline assembly instructions, run a +# small program that executes the xgetbv instruction with input OP. This +# can be used to detect if the OS supports AVX instruction usage. +# +# On output, the values of the eax and edx registers are stored as +# hexadecimal strings as "eax:edx" in the cache variable +# ax_cv_gcc_x86_avx_xgetbv. +# +# If the xgetbv instruction fails (because you are running a +# cross-compiler, or because you are not using gcc, or because you are on +# a processor that doesn't have this instruction), +# ax_cv_gcc_x86_avx_xgetbv_OP is set to the string "unknown". +# +# This macro mainly exists to be used in AX_EXT. +# +# LICENSE +# +# Copyright (c) 2013 Michael Petch +# +# 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 3 of the License, 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, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 1 + +AC_DEFUN([AX_GCC_X86_AVX_XGETBV], +[AC_REQUIRE([AC_PROG_CC]) +AC_LANG_PUSH([C]) +AC_CACHE_CHECK(for x86-AVX xgetbv $1 output, ax_cv_gcc_x86_avx_xgetbv_$1, + [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ + int op = $1, eax, edx; + FILE *f; + /* Opcodes for xgetbv */ + __asm__(".byte 0x0f, 0x01, 0xd0" + : "=a" (eax), "=d" (edx) + : "c" (op)); + f = fopen("conftest_xgetbv", "w"); if (!f) return 1; + fprintf(f, "%x:%x\n", eax, edx); + fclose(f); + return 0; +])], + [ax_cv_gcc_x86_avx_xgetbv_$1=`cat conftest_xgetbv`; rm -f conftest_xgetbv], + [ax_cv_gcc_x86_avx_xgetbv_$1=unknown; rm -f conftest_xgetbv], + [ax_cv_gcc_x86_avx_xgetbv_$1=unknown])]) +AC_LANG_POP([C]) +]) diff --git a/m4/ax_gcc_x86_cpuid.m4 b/m4/ax_gcc_x86_cpuid.m4 new file mode 100644 index 0000000..7d46fee --- /dev/null +++ b/m4/ax_gcc_x86_cpuid.m4 @@ -0,0 +1,79 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_gcc_x86_cpuid.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_GCC_X86_CPUID(OP) +# +# DESCRIPTION +# +# On Pentium and later x86 processors, with gcc or a compiler that has a +# compatible syntax for inline assembly instructions, run a small program +# that executes the cpuid instruction with input OP. This can be used to +# detect the CPU type. +# +# On output, the values of the eax, ebx, ecx, and edx registers are stored +# as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable +# ax_cv_gcc_x86_cpuid_OP. +# +# If the cpuid instruction fails (because you are running a +# cross-compiler, or because you are not using gcc, or because you are on +# a processor that doesn't have this instruction), ax_cv_gcc_x86_cpuid_OP +# is set to the string "unknown". +# +# This macro mainly exists to be used in AX_GCC_ARCHFLAG. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2008 Matteo Frigo +# +# 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 3 of the License, 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, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 7 + +AC_DEFUN([AX_GCC_X86_CPUID], +[AC_REQUIRE([AC_PROG_CC]) +AC_LANG_PUSH([C]) +AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1, + [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ + int op = $1, eax, ebx, ecx, edx; + FILE *f; + __asm__("cpuid" + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "a" (op)); + f = fopen("conftest_cpuid", "w"); if (!f) return 1; + fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); + fclose(f); + return 0; +])], + [ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid], + [ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid], + [ax_cv_gcc_x86_cpuid_$1=unknown])]) +AC_LANG_POP([C]) +]) diff --git a/m4/ax_require_defined.m4 b/m4/ax_require_defined.m4 new file mode 100644 index 0000000..cae1111 --- /dev/null +++ b/m4/ax_require_defined.m4 @@ -0,0 +1,37 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_require_defined.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_REQUIRE_DEFINED(MACRO) +# +# DESCRIPTION +# +# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have +# been defined and thus are available for use. This avoids random issues +# where a macro isn't expanded. Instead the configure script emits a +# non-fatal: +# +# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found +# +# It's like AC_REQUIRE except it doesn't expand the required macro. +# +# Here's an example: +# +# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) +# +# LICENSE +# +# Copyright (c) 2014 Mike Frysinger +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +AC_DEFUN([AX_REQUIRE_DEFINED], [dnl + m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) +])dnl AX_REQUIRE_DEFINED diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..070f545 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,22 @@ +# Jerasure AM file + +AM_CPPFLAGS = -I$(top_srcdir)/include +AM_CFLAGS = $(SIMD_FLAGS) + +lib_LTLIBRARIES = libJerasure.la +libJerasure_la_SOURCES = galois.c jerasure.c reed_sol.c cauchy.c liberation.c +libJerasure_la_LDFLAGS = -version-info 2:0:0 +libJerasure_la_LIBADD = -lgf_complete +include_HEADERS = ../include/jerasure.h + +# Install additional Jerasure header files in their own directory. +jerasureincludedir = $(includedir)/jerasure +jerasureinclude_HEADERS = \ + ../include/cauchy.h \ + ../include/galois.h \ + ../include/liberation.h \ + ../include/reed_sol.h + +noinst_HEADERS = ../include/timing.h +noinst_LIBRARIES = libtiming.a +libtiming_a_SOURCES = timing.c diff --git a/src/cauchy.c b/src/cauchy.c new file mode 100644 index 0000000..f63dfb7 --- /dev/null +++ b/src/cauchy.c @@ -0,0 +1,405 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank + */ + +#include +#include +#include + +#include "galois.h" +#include "jerasure.h" +#include "cauchy.h" + +static int PPs[33] = { -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1 }; +static int NOs[33]; +static int ONEs[33][33]; + +static int *cbest_0; +static int *cbest_1; +static int cbest_2[3]; +static int cbest_3[7]; +static int cbest_4[15]; +static int cbest_5[31]; +static int cbest_6[63]; +static int cbest_7[127]; +static int cbest_8[255]; +static int cbest_9[511]; +static int cbest_10[1023]; +static int cbest_11[1023]; +static int *cbest_12, *cbest_13, *cbest_14, *cbest_15, *cbest_16, *cbest_17, *cbest_18, *cbest_19, *cbest_20, + *cbest_21, *cbest_22, *cbest_23, *cbest_24, *cbest_25, *cbest_26, *cbest_27, *cbest_28, *cbest_29, *cbest_30, + *cbest_31, *cbest_32; + +static int cbest_max_k[33] = { -1, -1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 1023, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1 }; + +static int cbest_init = 0; + +static int *cbest_all[33]; + + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +int cauchy_n_ones(int n, int w) +{ + int no; + int cno; + int nones; + int i, j; + int highbit; + + highbit = (1 << (w-1)); + + if (PPs[w] == -1) { + nones = 0; + PPs[w] = galois_single_multiply(highbit, 2, w); + for (i = 0; i < w; i++) { + if (PPs[w] & (1 << i)) { + ONEs[w][nones] = (1 << i); + nones++; + } + } + NOs[w] = nones; + } + + no = 0; + for (i = 0; i < w; i++) if (n & (1 << i)) no++; + cno = no; + for (i = 1; i < w; i++) { + if (n & highbit) { + n ^= highbit; + n <<= 1; + n ^= PPs[w]; + cno--; + for (j = 0; j < NOs[w]; j++) { + cno += (n & ONEs[w][j]) ? 1 : -1; + } + } else { + n <<= 1; + } + no += cno; + } + return no; +} + +int *cauchy_original_coding_matrix(int k, int m, int w) +{ + int *matrix; + int i, j, index; + + if (w < 31 && (k+m) > (1 << w)) return NULL; + matrix = talloc(int, k*m); + if (matrix == NULL) return NULL; + index = 0; + for (i = 0; i < m; i++) { + for (j = 0; j < k; j++) { + matrix[index] = galois_single_divide(1, (i ^ (m+j)), w); + index++; + } + } + return matrix; +} + +int *cauchy_xy_coding_matrix(int k, int m, int w, int *X, int *Y) +{ + int index, i, j; + int *matrix; + + matrix = talloc(int, k*m); + if (matrix == NULL) { return NULL; } + index = 0; + for (i = 0; i < m; i++) { + for (j = 0; j < k; j++) { + matrix[index] = galois_single_divide(1, (X[i] ^ Y[j]), w); + index++; + } + } + return matrix; +} + +void cauchy_improve_coding_matrix(int k, int m, int w, int *matrix) +{ + int index, i, j, x; + int tmp; + int bno, tno, bno_index; + + for (j = 0; j < k; j++) { + if (matrix[j] != 1) { + tmp = galois_single_divide(1, matrix[j], w); + index = j; + for (i = 0; i < m; i++) { + matrix[index] = galois_single_multiply(matrix[index], tmp, w); + index += k; + } + } + } + for (i = 1; i < m; i++) { + bno = 0; + index = i*k; + for (j = 0; j < k; j++) bno += cauchy_n_ones(matrix[index+j], w); + bno_index = -1; + for (j = 0; j < k; j++) { + if (matrix[index+j] != 1) { + tmp = galois_single_divide(1, matrix[index+j], w); + tno = 0; + for (x = 0; x < k; x++) { + tno += cauchy_n_ones(galois_single_multiply(matrix[index+x], tmp, w), w); + } + if (tno < bno) { + bno = tno; + bno_index = j; + } + } + } + if (bno_index != -1) { + tmp = galois_single_divide(1, matrix[index+bno_index], w); + for (j = 0; j < k; j++) { + matrix[index+j] = galois_single_multiply(matrix[index+j], tmp, w); + } + } + } +} + +int *cauchy_good_general_coding_matrix(int k, int m, int w) +{ + int *matrix, i; + + if (m == 2 && k <= cbest_max_k[w]) { + matrix = talloc(int, k*m); + if (matrix == NULL) return NULL; + if (!cbest_init) { + cbest_init = 1; + cbest_all[0] = cbest_0; cbest_all[1] = cbest_1; cbest_all[2] = cbest_2; cbest_all[3] = cbest_3; cbest_all[4] = + cbest_4; cbest_all[5] = cbest_5; cbest_all[6] = cbest_6; cbest_all[7] = cbest_7; cbest_all[8] = cbest_8; + cbest_all[9] = cbest_9; cbest_all[10] = cbest_10; cbest_all[11] = cbest_11; cbest_all[12] = cbest_12; + cbest_all[13] = cbest_13; cbest_all[14] = cbest_14; cbest_all[15] = cbest_15; cbest_all[16] = cbest_16; + cbest_all[17] = cbest_17; cbest_all[18] = cbest_18; cbest_all[19] = cbest_19; cbest_all[20] = cbest_20; + cbest_all[21] = cbest_21; cbest_all[22] = cbest_22; cbest_all[23] = cbest_23; cbest_all[24] = cbest_24; + cbest_all[25] = cbest_25; cbest_all[26] = cbest_26; cbest_all[27] = cbest_27; cbest_all[28] = cbest_28; + cbest_all[29] = cbest_29; cbest_all[30] = cbest_30; cbest_all[31] = cbest_31; cbest_all[32] = (int *) cbest_32; + } + for (i = 0; i < k; i++) { + matrix[i] = 1; + matrix[i+k] = cbest_all[w][i]; + } + return matrix; + } else { + matrix = cauchy_original_coding_matrix(k, m, w); + if (matrix == NULL) return NULL; + cauchy_improve_coding_matrix(k, m, w, matrix); + return matrix; + } +} + +static int cbest_2[3] = { 1, 2, 3 }; +static int cbest_3[7] = { 1, 2, 5, 4, 7, 3, 6 }; + +static int cbest_4[15] = { 1, 2, 9, 4, 8, 13, 3, 6, 12, 5, 11, 15, 10, 14, 7 }; + +static int cbest_5[31] = { 1, 2, 18, 4, 9, 8, 22, 16, 3, 11, 19, 5, 10, 6, 20, 27, 13, 23, 26, 12, + 17, 25, 24, 31, 30, 7, 15, 21, 29, 14, 28 }; + +static int cbest_6[63] = { 1, 2, 33, 4, 8, 49, 16, 32, 57, 3, 6, 12, 24, 48, 5, 35, 9, 37, 10, 17, + 41, 51, 56, 61, 18, 28, 53, 14, 20, 34, 7, 13, 25, 36, 59, 26, 39, 40, 45, 50, 60, 52, 63, + 11, 30, 55, 19, 22, 29, 43, 58, 15, 21, 38, 44, 47, 62, 27, 54, 42, 31, 23, 46 }; + +static int cbest_7[127] = { 1, 2, 68, 4, 34, 8, 17, 16, 76, 32, 38, 3, 64, 69, 5, 19, 35, 70, 6, 9, + 18, 102, 10, 36, 85, 12, 21, 42, 51, 72, 77, 84, 20, 25, 33, 50, 78, 98, 24, 39, 49, 100, 110 + , 48, 65, 93, 40, 66, 71, 92, 7, 46, 55, 87, 96, 103, 106, 11, 23, 37, 54, 81, 86, 108, 13, + 22, 27, 43, 53, 73, 80, 14, 26, 52, 74, 79, 99, 119, 44, 95, 101, 104, 111, 118, 29, 59, 89, + 94, 117, 28, 41, 58, 67, 88, 115, 116, 47, 57, 83, 97, 107, 114, 127, 56, 82, 109, 113, 126, + 112, 125, 15, 63, 75, 123, 124, 31, 45, 62, 91, 105, 122, 30, 61, 90, 121, 60, 120 }; + +static int cbest_8[255] = { 1, 2, 142, 4, 71, 8, 70, 173, 3, 35, 143, 16, 17, 67, 134, 140, 172, 6, 34 + , 69, 201, 216, 5, 33, 86, 12, 65, 138, 158, 159, 175, 10, 32, 43, 66, 108, 130, 193, 234, 9, + 24, 25, 50, 68, 79, 100, 132, 174, 200, 217, 20, 21, 42, 48, 87, 169, 41, 54, 64, 84, 96, 117 + , 154, 155, 165, 226, 77, 82, 135, 136, 141, 168, 192, 218, 238, 7, 18, 19, 39, 40, 78, 113, + 116, 128, 164, 180, 195, 205, 220, 232, 14, 26, 27, 58, 109, 156, 157, 203, 235, 13, 28, 29, 38 + , 51, 56, 75, 85, 90, 101, 110, 112, 139, 171, 11, 37, 49, 52, 76, 83, 102, 119, 131, 150, 151 + , 167, 182, 184, 188, 197, 219, 224, 45, 55, 80, 94, 97, 133, 170, 194, 204, 221, 227, 236, 36, + 47, 73, 92, 98, 104, 118, 152, 153, 166, 202, 207, 239, 251, 22, 23, 44, 74, 91, 148, 149, 161 + , 181, 190, 233, 46, 59, 88, 137, 146, 147, 163, 196, 208, 212, 222, 250, 57, 81, 95, 106, 111, + 129, 160, 176, 199, 243, 249, 15, 53, 72, 93, 103, 115, 125, 162, 183, 185, 189, 206, 225, 255, + 186, 210, 230, 237, 242, 248, 30, 31, 62, 89, 99, 105, 114, 121, 124, 178, 209, 213, 223, 228, + 241, 254, 60, 191, 198, 247, 120, 240, 107, 127, 144, 145, 177, 211, 214, 246, 245, 123, 126, + 187, 231, 253, 63, 179, 229, 244, 61, 122, 215, 252 }; + +static int cbest_9[511] = { 1, 2, 264, 4, 132, 8, 66, 16, 33, 32, 280, 64, 140, 128, 3, 70, 265, 5, + 133, 256, 266, 6, 9, 35, 67, 134, 268, 396, 10, 17, 34, 330, 12, 18, 68, 198, 297, 20, 37, 74 + , 136, 148, 165, 281, 296, 24, 36, 41, 65, 82, 99, 164, 272, 282, 388, 40, 49, 98, 141, 194, + 284, 328, 412, 48, 97, 129, 142, 196, 346, 71, 72, 96, 130, 313, 392, 80, 206, 257, 267, 312, + 334, 7, 135, 156, 173, 192, 258, 269, 397, 404, 11, 78, 144, 161, 172, 260, 270, 299, 331, 344, + 398, 13, 19, 39, 69, 86, 103, 160, 167, 199, 202, 298, 322, 384, 14, 21, 38, 43, 75, 102, 137, + 149, 166, 204, 289, 332, 408, 462, 22, 25, 42, 51, 83, 101, 138, 150, 273, 283, 288, 301, 350, + 389, 429, 26, 50, 76, 100, 195, 274, 285, 300, 329, 363, 390, 413, 428, 28, 45, 84, 143, 197, + 200, 214, 231, 276, 286, 315, 320, 347, 362, 414, 458, 44, 53, 73, 90, 107, 131, 152, 169, 181, + 230, 314, 338, 361, 393, 400, 454, 460, 52, 57, 81, 106, 115, 168, 175, 180, 207, 229, 305, 335 + , 348, 360, 394, 421, 478, 56, 105, 114, 157, 163, 174, 193, 210, 227, 228, 259, 304, 317, 326, + 405, 420, 445, 79, 104, 113, 145, 158, 162, 212, 226, 261, 271, 316, 345, 379, 399, 406, 444, + 450, 456, 87, 88, 112, 146, 203, 225, 262, 291, 323, 336, 378, 385, 425, 452, 474, 15, 205, 222 + , 224, 239, 290, 303, 333, 367, 377, 386, 409, 424, 431, 463, 470, 476, 23, 139, 151, 189, 208, + 238, 302, 324, 351, 366, 376, 410, 430, 437, 27, 47, 77, 94, 111, 177, 188, 237, 275, 293, 342, + 365, 391, 436, 448, 29, 46, 55, 85, 110, 119, 171, 176, 183, 201, 215, 218, 235, 236, 277, 287, + 292, 321, 355, 364, 415, 417, 459, 466, 472, 30, 54, 59, 91, 109, 118, 153, 170, 182, 220, 234, + 278, 307, 339, 354, 401, 416, 423, 441, 455, 461, 468, 495, 58, 108, 117, 154, 233, 306, 319, + 349, 353, 383, 395, 402, 422, 440, 447, 479, 494, 92, 116, 211, 232, 318, 327, 340, 352, 382, + 446, 493, 61, 159, 213, 216, 247, 309, 381, 407, 427, 451, 457, 464, 491, 492, 60, 89, 123, 147 + , 185, 246, 263, 308, 337, 371, 380, 426, 433, 453, 475, 487, 490, 122, 184, 191, 223, 245, 370, + 387, 432, 439, 471, 477, 486, 489, 511, 121, 179, 190, 209, 243, 244, 295, 325, 359, 369, 411, + 438, 485, 488, 510, 95, 120, 178, 242, 294, 343, 358, 368, 419, 449, 483, 484, 509, 219, 241, + 357, 418, 443, 467, 473, 482, 507, 508, 31, 221, 240, 255, 279, 356, 442, 469, 481, 503, 506, + 155, 254, 403, 480, 502, 505, 63, 93, 127, 253, 311, 341, 375, 501, 504, 62, 126, 187, 217, 251 + , 252, 310, 374, 435, 465, 499, 500, 125, 186, 250, 373, 434, 498, 124, 249, 372, 497, 248, 496 + }; + +static int cbest_10[1023] = { 1, 2, 516, 4, 258, 8, 129, 16, 32, 580, 64, 128, 290, 145, 256, 3, 512, + 517, 5, 259, 518, 588, 6, 9, 18, 36, 72, 144, 774, 10, 17, 131, 262, 288, 524, 645, 12, 33, + 133, 266, 294, 387, 532, 576, 581, 20, 34, 65, 137, 274, 548, 582, 24, 66, 291, 838, 40, 68, + 130, 147, 161, 322, 644, 709, 806, 48, 132, 193, 257, 386, 596, 80, 136, 298, 419, 612, 661, 772 + , 96, 149, 260, 272, 306, 403, 513, 146, 153, 160, 264, 292, 385, 514, 519, 544, 584, 589, 708, + 870, 7, 19, 37, 73, 192, 354, 590, 770, 775, 11, 38, 74, 177, 263, 289, 418, 520, 525, 534, 641 + , 660, 725, 802, 836, 846, 13, 22, 76, 148, 209, 267, 295, 320, 330, 402, 526, 528, 533, 577, + 647, 717, 804, 14, 21, 26, 35, 44, 135, 152, 165, 201, 275, 304, 384, 401, 435, 549, 578, 583, + 604, 608, 782, 903, 25, 52, 67, 88, 139, 270, 296, 391, 417, 550, 620, 653, 790, 834, 839, 41, + 50, 69, 104, 141, 176, 278, 302, 323, 395, 423, 540, 598, 640, 705, 724, 807, 866, 28, 42, 49, + 70, 82, 100, 163, 208, 282, 310, 556, 592, 597, 646, 663, 677, 711, 716, 868, 878, 81, 134, 151 + , 164, 195, 200, 299, 326, 352, 362, 400, 434, 564, 613, 657, 768, 773, 902, 967, 97, 138, 155, + 169, 197, 261, 273, 307, 358, 390, 416, 433, 451, 614, 652, 733, 800, 814, 844, 854, 935, 56, 84 + , 98, 140, 181, 217, 265, 293, 328, 338, 394, 422, 515, 545, 585, 704, 788, 822, 871, 919, 162, + 179, 276, 355, 407, 427, 546, 586, 591, 616, 662, 669, 676, 710, 727, 741, 771, 780, 901, 39, 75 + , 150, 157, 194, 211, 225, 268, 280, 308, 314, 389, 411, 439, 521, 530, 535, 628, 656, 721, 803, + 832, 837, 842, 847, 966, 23, 77, 112, 154, 168, 196, 300, 321, 331, 393, 421, 432, 450, 522, 527 + , 529, 552, 606, 643, 673, 693, 713, 732, 805, 864, 874, 934, 999, 15, 27, 45, 54, 78, 90, 108, + 180, 216, 305, 483, 560, 579, 600, 605, 609, 719, 778, 783, 852, 876, 886, 899, 918, 983, 46, 53 + , 89, 167, 178, 185, 203, 213, 271, 297, 324, 334, 336, 360, 370, 406, 426, 467, 542, 551, 610, + 621, 649, 668, 726, 740, 786, 791, 810, 820, 835, 900, 917, 931, 951, 965, 975, 30, 51, 105, 156 + , 205, 210, 224, 279, 303, 356, 366, 388, 405, 410, 438, 449, 459, 536, 541, 594, 599, 622, 655, + 720, 812, 818, 862, 867, 933, 29, 43, 71, 83, 92, 101, 106, 143, 173, 283, 311, 312, 346, 392, + 409, 420, 437, 443, 557, 566, 593, 642, 659, 672, 692, 707, 712, 737, 757, 869, 879, 911, 998, + 60, 102, 241, 327, 353, 363, 399, 425, 482, 558, 565, 624, 679, 718, 735, 749, 769, 798, 898, + 963, 982, 58, 86, 166, 183, 184, 202, 212, 219, 233, 286, 359, 431, 466, 615, 636, 648, 689, 729 + , 801, 815, 840, 845, 850, 855, 884, 916, 930, 950, 964, 974, 981, 995, 1015, 57, 85, 99, 120, + 171, 199, 204, 229, 318, 329, 339, 368, 404, 448, 458, 465, 499, 654, 671, 685, 784, 789, 823, + 872, 882, 915, 932, 949, 997, 1007, 116, 142, 159, 172, 277, 408, 436, 442, 455, 481, 491, 547, + 572, 587, 617, 630, 658, 665, 706, 723, 736, 756, 776, 781, 816, 860, 894, 897, 910, 947, 991, + 114, 221, 240, 269, 281, 309, 315, 332, 342, 344, 378, 398, 424, 441, 475, 487, 531, 618, 629, + 678, 695, 734, 743, 748, 808, 833, 843, 929, 943, 962, 973, 113, 182, 189, 218, 227, 232, 301, + 364, 374, 430, 457, 523, 553, 562, 602, 607, 688, 728, 753, 796, 830, 865, 875, 927, 980, 994, + 1014, 55, 79, 91, 109, 170, 187, 198, 215, 228, 284, 415, 464, 498, 554, 561, 601, 670, 675, 684 + , 715, 745, 765, 779, 848, 853, 877, 887, 909, 914, 948, 979, 996, 1006, 1013, 47, 110, 158, 249 + , 316, 325, 335, 337, 361, 371, 397, 447, 454, 480, 490, 497, 538, 543, 611, 632, 664, 722, 787, + 811, 821, 880, 896, 913, 946, 961, 971, 990, 1011, 31, 94, 220, 245, 357, 367, 429, 440, 474, + 486, 537, 595, 623, 651, 681, 694, 701, 742, 759, 813, 819, 858, 863, 892, 928, 942, 945, 972, + 989, 993, 1003, 1023, 62, 93, 107, 188, 207, 226, 237, 243, 313, 340, 347, 376, 456, 471, 473, + 507, 567, 568, 626, 752, 890, 907, 926, 1005, 61, 103, 124, 175, 186, 214, 372, 414, 453, 463, + 489, 503, 559, 625, 638, 674, 691, 714, 731, 739, 744, 764, 794, 799, 828, 908, 925, 939, 959, + 978, 1012, 59, 87, 122, 248, 287, 350, 396, 413, 446, 485, 495, 496, 637, 751, 826, 841, 851, + 885, 912, 941, 960, 970, 977, 1010, 118, 121, 235, 244, 319, 369, 382, 428, 445, 574, 650, 667, + 680, 700, 758, 761, 785, 873, 883, 944, 988, 992, 1002, 1009, 1022, 117, 206, 223, 231, 236, 242 + , 470, 472, 506, 573, 631, 687, 777, 817, 856, 861, 895, 906, 987, 1004, 1021, 115, 174, 191, 333 + , 343, 345, 379, 452, 462, 469, 488, 502, 505, 619, 690, 697, 730, 738, 755, 809, 888, 924, 938, + 958, 969, 1019, 253, 365, 375, 412, 484, 494, 501, 563, 603, 750, 767, 792, 797, 831, 923, 940, + 957, 976, 1001, 234, 251, 285, 348, 444, 479, 555, 634, 666, 760, 824, 849, 905, 955, 1008, 111, + 222, 230, 247, 317, 380, 461, 511, 539, 633, 686, 703, 747, 881, 937, 986, 1020, 95, 190, 468, + 493, 504, 570, 696, 754, 859, 893, 968, 985, 1018, 63, 126, 252, 341, 377, 500, 569, 627, 683, + 766, 891, 922, 956, 1000, 1017, 125, 239, 250, 373, 478, 639, 795, 829, 904, 921, 954, 123, 246, + 351, 460, 477, 510, 702, 746, 763, 827, 936, 953, 119, 383, 492, 509, 575, 984, 682, 699, 857, + 1016, 238, 255, 889, 920, 476, 762, 793, 952, 349, 508, 635, 825, 381, 698, 254, 571, 127 }; + +static int cbest_11[1023] = { 1, + 2, 1026, 4, 513, 8, 16, 1282, 32, 64, 641, 128, 256, 512, 1346, 1024, 3, 673, 1027, 5, 10, 20, 40, 80, 160, 320, + 640, 6, 9, 515, 1030, 1280, 1539, 17, 517, 1034, 1283, 12, 18, 33, 521, 1042, 1362, 34, 65, 529, 1058, 1286, 1795, + 24, 36, 66, 129, 545, 643, 1090, 1290, 1667, 68, 130, 257, 577, 645, 672, 1154, 1298, 1344, 48, 72, 132, 258, 336, + 649, 681, 1314, 1347, 136, 168, 260, 514, 657, 769, 1538, 1923, 84, 96, 144, 264, 516, 1025, 1350, 1410, 1859, 42, + 272, 520, 705, 1032, 1354, 11, 21, 41, 81, 161, 192, 288, 321, 528, 675, 1028, 1537, 1699, 1794, 7, 22, 82, 162, + 322, 544, 642, 677, 897, 1031, 1046, 1066, 1106, 1186, 1281, 1366, 1378, 1666, 14, 44, 164, 324, 384, 523, 533, + 553, 576, 593, 644, 833, 1035, 1040, 1288, 1360, 1987, 13, 19, 28, 88, 328, 519, 648, 680, 689, 1043, 1056, 1284, + 1363, 1474, 1543, 1793, 1955, 26, 35, 56, 176, 656, 768, 1038, 1059, 1088, 1287, 1302, 1322, 1442, 1547, 1665, + 1922, 25, 37, 52, 67, 112, 340, 352, 525, 531, 737, 1091, 1152, 1291, 1296, 1555, 1858, 1875, 38, 69, 74, 104, 131, + 224, 547, 651, 661, 683, 704, 721, 961, 1050, 1062, 1155, 1299, 1312, 1345, 1370, 1571, 1799, 49, 70, 73, 133, 138, + 148, 170, 208, 259, 337, 448, 537, 549, 579, 647, 674, 929, 1094, 1294, 1315, 1352, 1536, 1603, 1671, 1698, 1803, + 1921, 50, 134, 137, 169, 261, 266, 276, 296, 338, 416, 581, 676, 896, 1074, 1098, 1158, 1348, 1394, 1408, 1675, + 1707, 1811, 1857, 2019, 76, 85, 97, 145, 262, 265, 522, 532, 552, 561, 585, 592, 653, 659, 685, 771, 832, 849, + 1064, 1162, 1194, 1306, 1318, 1351, 1386, 1411, 1506, 1683, 1827, 1986, 2003, 43, 86, 98, 140, 146, 172, 273, 344, + 518, 688, 773, 1033, 1110, 1122, 1170, 1355, 1490, 1542, 1697, 1792, 1927, 1954, 100, 193, 268, 274, 289, 597, 609, + 665, 697, 707, 777, 1029, 1044, 1104, 1184, 1330, 1364, 1376, 1414, 1546, 1664, 1731, 1863, 1931, 1963, 23, 46, 83, + 92, 152, 163, 184, 194, 290, 323, 368, 524, 530, 555, 693, 709, 736, 753, 785, 993, 1036, 1047, 1067, 1107, 1187, + 1218, 1320, 1358, 1367, 1379, 1418, 1450, 1545, 1554, 1867, 1874, 1939, 1985, 15, 30, 45, 60, 90, 120, 165, 180, + 196, 240, 280, 292, 325, 330, 360, 385, 480, 546, 650, 660, 679, 682, 713, 720, 745, 801, 899, 960, 977, 1041, + 1289, 1361, 1426, 1472, 1541, 1570, 1703, 1798, 1953, 29, 58, 89, 116, 166, 200, 232, 326, 329, 386, 464, 535, 536, + 548, 578, 595, 646, 835, 901, 928, 1048, 1057, 1070, 1190, 1285, 1300, 1368, 1382, 1440, 1475, 1559, 1579, 1602, + 1619, 1670, 1802, 1879, 1891, 1920, 27, 57, 177, 304, 388, 527, 557, 580, 691, 725, 837, 905, 937, 1039, 1054, + 1089, 1114, 1292, 1303, 1323, 1374, 1443, 1553, 1674, 1706, 1715, 1801, 1810, 1856, 1873, 1991, 2018, 2035, 53, + 106, 113, 178, 212, 332, 341, 353, 392, 424, 541, 560, 584, 601, 652, 658, 684, 770, 841, 848, 913, 1060, 1082, + 1096, 1153, 1202, 1297, 1402, 1478, 1522, 1569, 1673, 1682, 1705, 1797, 1826, 1959, 1995, 2002, 2027, 39, 54, 75, + 105, 114, 225, 342, 354, 400, 539, 569, 739, 772, 1051, 1063, 1078, 1092, 1138, 1160, 1192, 1304, 1313, 1326, 1371, + 1384, 1398, 1446, 1482, 1514, 1551, 1601, 1669, 1696, 1763, 1815, 1835, 1926, 71, 139, 149, 171, 209, 226, 298, + 356, 449, 565, 596, 608, 625, 663, 664, 696, 706, 723, 741, 776, 853, 865, 963, 1072, 1095, 1130, 1156, 1250, 1295, + 1310, 1353, 1392, 1687, 1730, 1747, 1809, 1862, 1930, 1962, 1971, 2007, 2017, 51, 78, 108, 135, 150, 210, 228, 267, + 277, 297, 339, 348, 417, 450, 551, 554, 587, 617, 655, 687, 692, 708, 752, 784, 931, 965, 992, 1009, 1075, 1099, + 1159, 1174, 1234, 1316, 1338, 1349, 1395, 1409, 1458, 1494, 1504, 1544, 1563, 1575, 1681, 1825, 1866, 1883, 1929, + 1938, 1961, 1984, 2001, 77, 142, 174, 263, 278, 346, 376, 418, 452, 496, 583, 669, 678, 701, 712, 729, 744, 761, + 800, 898, 933, 969, 976, 1001, 1065, 1108, 1120, 1163, 1168, 1195, 1307, 1319, 1334, 1356, 1387, 1416, 1448, 1488, + 1507, 1540, 1607, 1702, 1807, 1865, 1925, 1952, 87, 99, 141, 147, 156, 173, 188, 216, 248, 270, 300, 345, 372, 420, + 456, 488, 534, 563, 594, 667, 699, 757, 779, 789, 809, 834, 851, 900, 1102, 1111, 1123, 1171, 1328, 1412, 1491, + 1558, 1578, 1587, 1611, 1618, 1679, 1711, 1729, 1861, 1878, 1890, 1907, 1943, 2023, 94, 101, 124, 154, 186, 244, + 269, 275, 284, 526, 556, 589, 690, 724, 775, 836, 904, 936, 945, 981, 1045, 1068, 1105, 1166, 1185, 1198, 1216, + 1331, 1365, 1377, 1390, 1415, 1430, 1510, 1552, 1577, 1714, 1800, 1819, 1831, 1872, 1899, 1937, 1990, 2034, 47, 62, + 93, 102, 122, 153, 185, 195, 282, 291, 312, 362, 369, 432, 468, 540, 599, 600, 611, 715, 747, 840, 857, 912, 1037, + 1052, 1112, 1126, 1219, 1321, 1359, 1372, 1419, 1424, 1451, 1568, 1623, 1635, 1672, 1691, 1701, 1704, 1723, 1796, + 1958, 1994, 2011, 2026, 2043, 31, 61, 91, 121, 181, 197, 202, 234, 241, 281, 293, 308, 331, 361, 370, 481, 538, + 568, 613, 695, 711, 738, 755, 781, 787, 995, 1080, 1118, 1178, 1188, 1210, 1380, 1400, 1427, 1473, 1498, 1530, + 1550, 1557, 1600, 1617, 1668, 1719, 1735, 1762, 1779, 1814, 1834, 1843, 1877, 1889, 1935, 1967, 1993, 2025, 2039, + 59, 117, 167, 182, 198, 201, 233, 242, 294, 327, 387, 465, 482, 559, 564, 605, 624, 662, 722, 740, 803, 852, 864, + 881, 907, 917, 939, 962, 979, 997, 1049, 1071, 1086, 1146, 1191, 1206, 1222, 1266, 1301, 1324, 1369, 1383, 1406, + 1422, 1441, 1454, 1480, 1512, 1526, 1549, 1686, 1713, 1739, 1746, 1771, 1808, 1833, 1871, 1970, 1989, 2006, 2016, + 2033, 118, 305, 334, 364, 389, 394, 404, 426, 466, 484, 543, 550, 573, 586, 603, 616, 633, 654, 686, 717, 749, 793, + 805, 843, 873, 903, 930, 964, 1008, 1055, 1115, 1128, 1142, 1200, 1226, 1258, 1293, 1308, 1375, 1476, 1520, 1562, + 1574, 1680, 1824 }; + diff --git a/src/cauchy_best_r6.c b/src/cauchy_best_r6.c new file mode 100644 index 0000000..8a52e59 --- /dev/null +++ b/src/cauchy_best_r6.c @@ -0,0 +1,1983 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank + */ + +#include +#include +#include + +#include "galois.h" +#include "jerasure.h" +#include "cauchy.h" + +static int PPs[33] = { -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1 }; +static int NOs[33]; +static int ONEs[33][33]; + +static int *cbest_0; +static int *cbest_1; +static int cbest_2[3]; +static int cbest_3[7]; +static int cbest_4[15]; +static int cbest_5[31]; +static int cbest_6[63]; +static int cbest_7[127]; +static int cbest_8[255]; +static int cbest_9[511]; +static int cbest_10[1023]; +static int cbest_11[1023]; +static int cbest_12[1023], cbest_13[1023], cbest_14[1023], cbest_15[1023], cbest_16[1023], cbest_17[1023], cbest_18[1023], + cbest_19[1023], cbest_20[1023], cbest_21[1023], cbest_22[1023], cbest_23[1023], cbest_24[1023], cbest_25[1023], + cbest_26[1023], cbest_27[1023], cbest_28[1023], cbest_29[1023], cbest_30[1023], cbest_31[1023]; +static unsigned int cbest_32[1023]; + +static int cbest_max_k[33] = { -1, -1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 1023, + 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, + 1023, 1023, 1023, 1023 }; + +static int cbest_init = 0; + +static int *cbest_all[33]; + + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +int cauchy_n_ones(int n, int w) +{ + int no; + int cno; + int nones; + int i, j; + int highbit; + + highbit = (1 << (w-1)); + + if (PPs[w] == -1) { + nones = 0; + PPs[w] = galois_single_multiply(highbit, 2, w); + for (i = 0; i < w; i++) { + if (PPs[w] & (1 << i)) { + ONEs[w][nones] = (1 << i); + nones++; + } + } + NOs[w] = nones; + } + + no = 0; + for (i = 0; i < w; i++) if (n & (1 << i)) no++; + cno = no; + for (i = 1; i < w; i++) { + if (n & highbit) { + n ^= highbit; + n <<= 1; + n ^= PPs[w]; + cno--; + for (j = 0; j < NOs[w]; j++) { + cno += (n & ONEs[w][j]) ? 1 : -1; + } + } else { + n <<= 1; + } + no += cno; + } + return no; +} + +int *cauchy_original_coding_matrix(int k, int m, int w) +{ + int *matrix; + int i, j, index; + + if (w < 31 && (k+m) > (1 << w)) return NULL; + matrix = talloc(int, k*m); + if (matrix == NULL) return NULL; + index = 0; + for (i = 0; i < m; i++) { + for (j = 0; j < k; j++) { + matrix[index] = galois_single_divide(1, (i ^ (m+j)), w); + index++; + } + } + return matrix; +} + +int *cauchy_xy_coding_matrix(int k, int m, int w, int *X, int *Y) +{ + int index, i, j; + int *matrix; + + matrix = talloc(int, k*m); + if (matrix == NULL) { return NULL; } + index = 0; + for (i = 0; i < m; i++) { + for (j = 0; j < k; j++) { + matrix[index] = galois_single_divide(1, (X[i] ^ Y[j]), w); + index++; + } + } + return matrix; +} + +void cauchy_improve_coding_matrix(int k, int m, int w, int *matrix) +{ + int index, i, j, x; + int tmp; + int bno, tno, bno_index; + + for (j = 0; j < k; j++) { + if (matrix[j] != 1) { + tmp = galois_single_divide(1, matrix[j], w); + index = j; + for (i = 0; i < m; i++) { + matrix[index] = galois_single_multiply(matrix[index], tmp, w); + index += k; + } + } + } + for (i = 1; i < m; i++) { + bno = 0; + index = i*k; + for (j = 0; j < k; j++) bno += cauchy_n_ones(matrix[index+j], w); + bno_index = -1; + for (j = 0; j < k; j++) { + if (matrix[index+j] != 1) { + tmp = galois_single_divide(1, matrix[index+j], w); + tno = 0; + for (x = 0; x < k; x++) { + tno += cauchy_n_ones(galois_single_multiply(matrix[index+x], tmp, w), w); + } + if (tno < bno) { + bno = tno; + bno_index = j; + } + } + } + if (bno_index != -1) { + tmp = galois_single_divide(1, matrix[index+bno_index], w); + for (j = 0; j < k; j++) { + matrix[index+j] = galois_single_multiply(matrix[index+j], tmp, w); + } + } + } +} + +int *cauchy_good_general_coding_matrix(int k, int m, int w) +{ + int *matrix, i; + + if (m == 2 && k <= cbest_max_k[w]) { + matrix = talloc(int, k*m); + if (matrix == NULL) return NULL; + if (!cbest_init) { + cbest_init = 1; + cbest_all[0] = cbest_0; cbest_all[1] = cbest_1; cbest_all[2] = cbest_2; cbest_all[3] = cbest_3; cbest_all[4] = + cbest_4; cbest_all[5] = cbest_5; cbest_all[6] = cbest_6; cbest_all[7] = cbest_7; cbest_all[8] = cbest_8; + cbest_all[9] = cbest_9; cbest_all[10] = cbest_10; cbest_all[11] = cbest_11; cbest_all[12] = cbest_12; + cbest_all[13] = cbest_13; cbest_all[14] = cbest_14; cbest_all[15] = cbest_15; cbest_all[16] = cbest_16; + cbest_all[17] = cbest_17; cbest_all[18] = cbest_18; cbest_all[19] = cbest_19; cbest_all[20] = cbest_20; + cbest_all[21] = cbest_21; cbest_all[22] = cbest_22; cbest_all[23] = cbest_23; cbest_all[24] = cbest_24; + cbest_all[25] = cbest_25; cbest_all[26] = cbest_26; cbest_all[27] = cbest_27; cbest_all[28] = cbest_28; + cbest_all[29] = cbest_29; cbest_all[30] = cbest_30; cbest_all[31] = cbest_31; cbest_all[32] = (int *) cbest_32; + } + for (i = 0; i < k; i++) { + matrix[i] = 1; + matrix[i+k] = cbest_all[w][i]; + } + return matrix; + } else { + matrix = cauchy_original_coding_matrix(k, m, w); + if (matrix == NULL) return NULL; + cauchy_improve_coding_matrix(k, m, w, matrix); + return matrix; + } +} + +static int cbest_2[3] = { 1, 2, 3 }; +static int cbest_3[7] = { 1, 2, 5, 4, 7, 3, 6 }; + +static int cbest_4[15] = { 1, 2, 9, 4, 8, 13, 3, 6, 12, 5, 11, 15, 10, 14, 7 }; + +static int cbest_5[31] = { 1, 2, 18, 4, 9, 8, 22, 16, 3, 11, 19, 5, 10, 6, 20, 27, 13, 23, 26, 12, + 17, 25, 24, 31, 30, 7, 15, 21, 29, 14, 28 }; + +static int cbest_6[63] = { 1, 2, 33, 4, 8, 49, 16, 32, 57, 3, 6, 12, 24, 48, 5, 35, 9, 37, 10, 17, + 41, 51, 56, 61, 18, 28, 53, 14, 20, 34, 7, 13, 25, 36, 59, 26, 39, 40, 45, 50, 60, 52, 63, + 11, 30, 55, 19, 22, 29, 43, 58, 15, 21, 38, 44, 47, 62, 27, 54, 42, 31, 23, 46 }; + +static int cbest_7[127] = { 1, 2, 68, 4, 34, 8, 17, 16, 76, 32, 38, 3, 64, 69, 5, 19, 35, 70, 6, 9, + 18, 102, 10, 36, 85, 12, 21, 42, 51, 72, 77, 84, 20, 25, 33, 50, 78, 98, 24, 39, 49, 100, 110 + , 48, 65, 93, 40, 66, 71, 92, 7, 46, 55, 87, 96, 103, 106, 11, 23, 37, 54, 81, 86, 108, 13, + 22, 27, 43, 53, 73, 80, 14, 26, 52, 74, 79, 99, 119, 44, 95, 101, 104, 111, 118, 29, 59, 89, + 94, 117, 28, 41, 58, 67, 88, 115, 116, 47, 57, 83, 97, 107, 114, 127, 56, 82, 109, 113, 126, + 112, 125, 15, 63, 75, 123, 124, 31, 45, 62, 91, 105, 122, 30, 61, 90, 121, 60, 120 }; + +static int cbest_8[255] = { 1, 2, 142, 4, 71, 8, 70, 173, 3, 35, 143, 16, 17, 67, 134, 140, 172, 6, 34 + , 69, 201, 216, 5, 33, 86, 12, 65, 138, 158, 159, 175, 10, 32, 43, 66, 108, 130, 193, 234, 9, + 24, 25, 50, 68, 79, 100, 132, 174, 200, 217, 20, 21, 42, 48, 87, 169, 41, 54, 64, 84, 96, 117 + , 154, 155, 165, 226, 77, 82, 135, 136, 141, 168, 192, 218, 238, 7, 18, 19, 39, 40, 78, 113, + 116, 128, 164, 180, 195, 205, 220, 232, 14, 26, 27, 58, 109, 156, 157, 203, 235, 13, 28, 29, 38 + , 51, 56, 75, 85, 90, 101, 110, 112, 139, 171, 11, 37, 49, 52, 76, 83, 102, 119, 131, 150, 151 + , 167, 182, 184, 188, 197, 219, 224, 45, 55, 80, 94, 97, 133, 170, 194, 204, 221, 227, 236, 36, + 47, 73, 92, 98, 104, 118, 152, 153, 166, 202, 207, 239, 251, 22, 23, 44, 74, 91, 148, 149, 161 + , 181, 190, 233, 46, 59, 88, 137, 146, 147, 163, 196, 208, 212, 222, 250, 57, 81, 95, 106, 111, + 129, 160, 176, 199, 243, 249, 15, 53, 72, 93, 103, 115, 125, 162, 183, 185, 189, 206, 225, 255, + 186, 210, 230, 237, 242, 248, 30, 31, 62, 89, 99, 105, 114, 121, 124, 178, 209, 213, 223, 228, + 241, 254, 60, 191, 198, 247, 120, 240, 107, 127, 144, 145, 177, 211, 214, 246, 245, 123, 126, + 187, 231, 253, 63, 179, 229, 244, 61, 122, 215, 252 }; + +static int cbest_9[511] = { 1, 2, 264, 4, 132, 8, 66, 16, 33, 32, 280, 64, 140, 128, 3, 70, 265, 5, + 133, 256, 266, 6, 9, 35, 67, 134, 268, 396, 10, 17, 34, 330, 12, 18, 68, 198, 297, 20, 37, 74 + , 136, 148, 165, 281, 296, 24, 36, 41, 65, 82, 99, 164, 272, 282, 388, 40, 49, 98, 141, 194, + 284, 328, 412, 48, 97, 129, 142, 196, 346, 71, 72, 96, 130, 313, 392, 80, 206, 257, 267, 312, + 334, 7, 135, 156, 173, 192, 258, 269, 397, 404, 11, 78, 144, 161, 172, 260, 270, 299, 331, 344, + 398, 13, 19, 39, 69, 86, 103, 160, 167, 199, 202, 298, 322, 384, 14, 21, 38, 43, 75, 102, 137, + 149, 166, 204, 289, 332, 408, 462, 22, 25, 42, 51, 83, 101, 138, 150, 273, 283, 288, 301, 350, + 389, 429, 26, 50, 76, 100, 195, 274, 285, 300, 329, 363, 390, 413, 428, 28, 45, 84, 143, 197, + 200, 214, 231, 276, 286, 315, 320, 347, 362, 414, 458, 44, 53, 73, 90, 107, 131, 152, 169, 181, + 230, 314, 338, 361, 393, 400, 454, 460, 52, 57, 81, 106, 115, 168, 175, 180, 207, 229, 305, 335 + , 348, 360, 394, 421, 478, 56, 105, 114, 157, 163, 174, 193, 210, 227, 228, 259, 304, 317, 326, + 405, 420, 445, 79, 104, 113, 145, 158, 162, 212, 226, 261, 271, 316, 345, 379, 399, 406, 444, + 450, 456, 87, 88, 112, 146, 203, 225, 262, 291, 323, 336, 378, 385, 425, 452, 474, 15, 205, 222 + , 224, 239, 290, 303, 333, 367, 377, 386, 409, 424, 431, 463, 470, 476, 23, 139, 151, 189, 208, + 238, 302, 324, 351, 366, 376, 410, 430, 437, 27, 47, 77, 94, 111, 177, 188, 237, 275, 293, 342, + 365, 391, 436, 448, 29, 46, 55, 85, 110, 119, 171, 176, 183, 201, 215, 218, 235, 236, 277, 287, + 292, 321, 355, 364, 415, 417, 459, 466, 472, 30, 54, 59, 91, 109, 118, 153, 170, 182, 220, 234, + 278, 307, 339, 354, 401, 416, 423, 441, 455, 461, 468, 495, 58, 108, 117, 154, 233, 306, 319, + 349, 353, 383, 395, 402, 422, 440, 447, 479, 494, 92, 116, 211, 232, 318, 327, 340, 352, 382, + 446, 493, 61, 159, 213, 216, 247, 309, 381, 407, 427, 451, 457, 464, 491, 492, 60, 89, 123, 147 + , 185, 246, 263, 308, 337, 371, 380, 426, 433, 453, 475, 487, 490, 122, 184, 191, 223, 245, 370, + 387, 432, 439, 471, 477, 486, 489, 511, 121, 179, 190, 209, 243, 244, 295, 325, 359, 369, 411, + 438, 485, 488, 510, 95, 120, 178, 242, 294, 343, 358, 368, 419, 449, 483, 484, 509, 219, 241, + 357, 418, 443, 467, 473, 482, 507, 508, 31, 221, 240, 255, 279, 356, 442, 469, 481, 503, 506, + 155, 254, 403, 480, 502, 505, 63, 93, 127, 253, 311, 341, 375, 501, 504, 62, 126, 187, 217, 251 + , 252, 310, 374, 435, 465, 499, 500, 125, 186, 250, 373, 434, 498, 124, 249, 372, 497, 248, 496 + }; + +static int cbest_10[1023] = { 1, 2, 516, 4, 258, 8, 129, 16, 32, 580, 64, 128, 290, 145, 256, 3, 512, + 517, 5, 259, 518, 588, 6, 9, 18, 36, 72, 144, 774, 10, 17, 131, 262, 288, 524, 645, 12, 33, + 133, 266, 294, 387, 532, 576, 581, 20, 34, 65, 137, 274, 548, 582, 24, 66, 291, 838, 40, 68, + 130, 147, 161, 322, 644, 709, 806, 48, 132, 193, 257, 386, 596, 80, 136, 298, 419, 612, 661, 772 + , 96, 149, 260, 272, 306, 403, 513, 146, 153, 160, 264, 292, 385, 514, 519, 544, 584, 589, 708, + 870, 7, 19, 37, 73, 192, 354, 590, 770, 775, 11, 38, 74, 177, 263, 289, 418, 520, 525, 534, 641 + , 660, 725, 802, 836, 846, 13, 22, 76, 148, 209, 267, 295, 320, 330, 402, 526, 528, 533, 577, + 647, 717, 804, 14, 21, 26, 35, 44, 135, 152, 165, 201, 275, 304, 384, 401, 435, 549, 578, 583, + 604, 608, 782, 903, 25, 52, 67, 88, 139, 270, 296, 391, 417, 550, 620, 653, 790, 834, 839, 41, + 50, 69, 104, 141, 176, 278, 302, 323, 395, 423, 540, 598, 640, 705, 724, 807, 866, 28, 42, 49, + 70, 82, 100, 163, 208, 282, 310, 556, 592, 597, 646, 663, 677, 711, 716, 868, 878, 81, 134, 151 + , 164, 195, 200, 299, 326, 352, 362, 400, 434, 564, 613, 657, 768, 773, 902, 967, 97, 138, 155, + 169, 197, 261, 273, 307, 358, 390, 416, 433, 451, 614, 652, 733, 800, 814, 844, 854, 935, 56, 84 + , 98, 140, 181, 217, 265, 293, 328, 338, 394, 422, 515, 545, 585, 704, 788, 822, 871, 919, 162, + 179, 276, 355, 407, 427, 546, 586, 591, 616, 662, 669, 676, 710, 727, 741, 771, 780, 901, 39, 75 + , 150, 157, 194, 211, 225, 268, 280, 308, 314, 389, 411, 439, 521, 530, 535, 628, 656, 721, 803, + 832, 837, 842, 847, 966, 23, 77, 112, 154, 168, 196, 300, 321, 331, 393, 421, 432, 450, 522, 527 + , 529, 552, 606, 643, 673, 693, 713, 732, 805, 864, 874, 934, 999, 15, 27, 45, 54, 78, 90, 108, + 180, 216, 305, 483, 560, 579, 600, 605, 609, 719, 778, 783, 852, 876, 886, 899, 918, 983, 46, 53 + , 89, 167, 178, 185, 203, 213, 271, 297, 324, 334, 336, 360, 370, 406, 426, 467, 542, 551, 610, + 621, 649, 668, 726, 740, 786, 791, 810, 820, 835, 900, 917, 931, 951, 965, 975, 30, 51, 105, 156 + , 205, 210, 224, 279, 303, 356, 366, 388, 405, 410, 438, 449, 459, 536, 541, 594, 599, 622, 655, + 720, 812, 818, 862, 867, 933, 29, 43, 71, 83, 92, 101, 106, 143, 173, 283, 311, 312, 346, 392, + 409, 420, 437, 443, 557, 566, 593, 642, 659, 672, 692, 707, 712, 737, 757, 869, 879, 911, 998, + 60, 102, 241, 327, 353, 363, 399, 425, 482, 558, 565, 624, 679, 718, 735, 749, 769, 798, 898, + 963, 982, 58, 86, 166, 183, 184, 202, 212, 219, 233, 286, 359, 431, 466, 615, 636, 648, 689, 729 + , 801, 815, 840, 845, 850, 855, 884, 916, 930, 950, 964, 974, 981, 995, 1015, 57, 85, 99, 120, + 171, 199, 204, 229, 318, 329, 339, 368, 404, 448, 458, 465, 499, 654, 671, 685, 784, 789, 823, + 872, 882, 915, 932, 949, 997, 1007, 116, 142, 159, 172, 277, 408, 436, 442, 455, 481, 491, 547, + 572, 587, 617, 630, 658, 665, 706, 723, 736, 756, 776, 781, 816, 860, 894, 897, 910, 947, 991, + 114, 221, 240, 269, 281, 309, 315, 332, 342, 344, 378, 398, 424, 441, 475, 487, 531, 618, 629, + 678, 695, 734, 743, 748, 808, 833, 843, 929, 943, 962, 973, 113, 182, 189, 218, 227, 232, 301, + 364, 374, 430, 457, 523, 553, 562, 602, 607, 688, 728, 753, 796, 830, 865, 875, 927, 980, 994, + 1014, 55, 79, 91, 109, 170, 187, 198, 215, 228, 284, 415, 464, 498, 554, 561, 601, 670, 675, 684 + , 715, 745, 765, 779, 848, 853, 877, 887, 909, 914, 948, 979, 996, 1006, 1013, 47, 110, 158, 249 + , 316, 325, 335, 337, 361, 371, 397, 447, 454, 480, 490, 497, 538, 543, 611, 632, 664, 722, 787, + 811, 821, 880, 896, 913, 946, 961, 971, 990, 1011, 31, 94, 220, 245, 357, 367, 429, 440, 474, + 486, 537, 595, 623, 651, 681, 694, 701, 742, 759, 813, 819, 858, 863, 892, 928, 942, 945, 972, + 989, 993, 1003, 1023, 62, 93, 107, 188, 207, 226, 237, 243, 313, 340, 347, 376, 456, 471, 473, + 507, 567, 568, 626, 752, 890, 907, 926, 1005, 61, 103, 124, 175, 186, 214, 372, 414, 453, 463, + 489, 503, 559, 625, 638, 674, 691, 714, 731, 739, 744, 764, 794, 799, 828, 908, 925, 939, 959, + 978, 1012, 59, 87, 122, 248, 287, 350, 396, 413, 446, 485, 495, 496, 637, 751, 826, 841, 851, + 885, 912, 941, 960, 970, 977, 1010, 118, 121, 235, 244, 319, 369, 382, 428, 445, 574, 650, 667, + 680, 700, 758, 761, 785, 873, 883, 944, 988, 992, 1002, 1009, 1022, 117, 206, 223, 231, 236, 242 + , 470, 472, 506, 573, 631, 687, 777, 817, 856, 861, 895, 906, 987, 1004, 1021, 115, 174, 191, 333 + , 343, 345, 379, 452, 462, 469, 488, 502, 505, 619, 690, 697, 730, 738, 755, 809, 888, 924, 938, + 958, 969, 1019, 253, 365, 375, 412, 484, 494, 501, 563, 603, 750, 767, 792, 797, 831, 923, 940, + 957, 976, 1001, 234, 251, 285, 348, 444, 479, 555, 634, 666, 760, 824, 849, 905, 955, 1008, 111, + 222, 230, 247, 317, 380, 461, 511, 539, 633, 686, 703, 747, 881, 937, 986, 1020, 95, 190, 468, + 493, 504, 570, 696, 754, 859, 893, 968, 985, 1018, 63, 126, 252, 341, 377, 500, 569, 627, 683, + 766, 891, 922, 956, 1000, 1017, 125, 239, 250, 373, 478, 639, 795, 829, 904, 921, 954, 123, 246, + 351, 460, 477, 510, 702, 746, 763, 827, 936, 953, 119, 383, 492, 509, 575, 984, 682, 699, 857, + 1016, 238, 255, 889, 920, 476, 762, 793, 952, 349, 508, 635, 825, 381, 698, 254, 571, 127 }; + +static int cbest_11[1023] = { 1, + 2, 1026, 4, 513, 8, 16, 1282, 32, 64, 641, 128, 256, 512, 1346, 1024, 3, 673, 1027, 5, 10, 20, 40, 80, 160, 320, + 640, 6, 9, 515, 1030, 1280, 1539, 17, 517, 1034, 1283, 12, 18, 33, 521, 1042, 1362, 34, 65, 529, 1058, 1286, 1795, + 24, 36, 66, 129, 545, 643, 1090, 1290, 1667, 68, 130, 257, 577, 645, 672, 1154, 1298, 1344, 48, 72, 132, 258, 336, + 649, 681, 1314, 1347, 136, 168, 260, 514, 657, 769, 1538, 1923, 84, 96, 144, 264, 516, 1025, 1350, 1410, 1859, 42, + 272, 520, 705, 1032, 1354, 11, 21, 41, 81, 161, 192, 288, 321, 528, 675, 1028, 1537, 1699, 1794, 7, 22, 82, 162, + 322, 544, 642, 677, 897, 1031, 1046, 1066, 1106, 1186, 1281, 1366, 1378, 1666, 14, 44, 164, 324, 384, 523, 533, + 553, 576, 593, 644, 833, 1035, 1040, 1288, 1360, 1987, 13, 19, 28, 88, 328, 519, 648, 680, 689, 1043, 1056, 1284, + 1363, 1474, 1543, 1793, 1955, 26, 35, 56, 176, 656, 768, 1038, 1059, 1088, 1287, 1302, 1322, 1442, 1547, 1665, + 1922, 25, 37, 52, 67, 112, 340, 352, 525, 531, 737, 1091, 1152, 1291, 1296, 1555, 1858, 1875, 38, 69, 74, 104, 131, + 224, 547, 651, 661, 683, 704, 721, 961, 1050, 1062, 1155, 1299, 1312, 1345, 1370, 1571, 1799, 49, 70, 73, 133, 138, + 148, 170, 208, 259, 337, 448, 537, 549, 579, 647, 674, 929, 1094, 1294, 1315, 1352, 1536, 1603, 1671, 1698, 1803, + 1921, 50, 134, 137, 169, 261, 266, 276, 296, 338, 416, 581, 676, 896, 1074, 1098, 1158, 1348, 1394, 1408, 1675, + 1707, 1811, 1857, 2019, 76, 85, 97, 145, 262, 265, 522, 532, 552, 561, 585, 592, 653, 659, 685, 771, 832, 849, + 1064, 1162, 1194, 1306, 1318, 1351, 1386, 1411, 1506, 1683, 1827, 1986, 2003, 43, 86, 98, 140, 146, 172, 273, 344, + 518, 688, 773, 1033, 1110, 1122, 1170, 1355, 1490, 1542, 1697, 1792, 1927, 1954, 100, 193, 268, 274, 289, 597, 609, + 665, 697, 707, 777, 1029, 1044, 1104, 1184, 1330, 1364, 1376, 1414, 1546, 1664, 1731, 1863, 1931, 1963, 23, 46, 83, + 92, 152, 163, 184, 194, 290, 323, 368, 524, 530, 555, 693, 709, 736, 753, 785, 993, 1036, 1047, 1067, 1107, 1187, + 1218, 1320, 1358, 1367, 1379, 1418, 1450, 1545, 1554, 1867, 1874, 1939, 1985, 15, 30, 45, 60, 90, 120, 165, 180, + 196, 240, 280, 292, 325, 330, 360, 385, 480, 546, 650, 660, 679, 682, 713, 720, 745, 801, 899, 960, 977, 1041, + 1289, 1361, 1426, 1472, 1541, 1570, 1703, 1798, 1953, 29, 58, 89, 116, 166, 200, 232, 326, 329, 386, 464, 535, 536, + 548, 578, 595, 646, 835, 901, 928, 1048, 1057, 1070, 1190, 1285, 1300, 1368, 1382, 1440, 1475, 1559, 1579, 1602, + 1619, 1670, 1802, 1879, 1891, 1920, 27, 57, 177, 304, 388, 527, 557, 580, 691, 725, 837, 905, 937, 1039, 1054, + 1089, 1114, 1292, 1303, 1323, 1374, 1443, 1553, 1674, 1706, 1715, 1801, 1810, 1856, 1873, 1991, 2018, 2035, 53, + 106, 113, 178, 212, 332, 341, 353, 392, 424, 541, 560, 584, 601, 652, 658, 684, 770, 841, 848, 913, 1060, 1082, + 1096, 1153, 1202, 1297, 1402, 1478, 1522, 1569, 1673, 1682, 1705, 1797, 1826, 1959, 1995, 2002, 2027, 39, 54, 75, + 105, 114, 225, 342, 354, 400, 539, 569, 739, 772, 1051, 1063, 1078, 1092, 1138, 1160, 1192, 1304, 1313, 1326, 1371, + 1384, 1398, 1446, 1482, 1514, 1551, 1601, 1669, 1696, 1763, 1815, 1835, 1926, 71, 139, 149, 171, 209, 226, 298, + 356, 449, 565, 596, 608, 625, 663, 664, 696, 706, 723, 741, 776, 853, 865, 963, 1072, 1095, 1130, 1156, 1250, 1295, + 1310, 1353, 1392, 1687, 1730, 1747, 1809, 1862, 1930, 1962, 1971, 2007, 2017, 51, 78, 108, 135, 150, 210, 228, 267, + 277, 297, 339, 348, 417, 450, 551, 554, 587, 617, 655, 687, 692, 708, 752, 784, 931, 965, 992, 1009, 1075, 1099, + 1159, 1174, 1234, 1316, 1338, 1349, 1395, 1409, 1458, 1494, 1504, 1544, 1563, 1575, 1681, 1825, 1866, 1883, 1929, + 1938, 1961, 1984, 2001, 77, 142, 174, 263, 278, 346, 376, 418, 452, 496, 583, 669, 678, 701, 712, 729, 744, 761, + 800, 898, 933, 969, 976, 1001, 1065, 1108, 1120, 1163, 1168, 1195, 1307, 1319, 1334, 1356, 1387, 1416, 1448, 1488, + 1507, 1540, 1607, 1702, 1807, 1865, 1925, 1952, 87, 99, 141, 147, 156, 173, 188, 216, 248, 270, 300, 345, 372, 420, + 456, 488, 534, 563, 594, 667, 699, 757, 779, 789, 809, 834, 851, 900, 1102, 1111, 1123, 1171, 1328, 1412, 1491, + 1558, 1578, 1587, 1611, 1618, 1679, 1711, 1729, 1861, 1878, 1890, 1907, 1943, 2023, 94, 101, 124, 154, 186, 244, + 269, 275, 284, 526, 556, 589, 690, 724, 775, 836, 904, 936, 945, 981, 1045, 1068, 1105, 1166, 1185, 1198, 1216, + 1331, 1365, 1377, 1390, 1415, 1430, 1510, 1552, 1577, 1714, 1800, 1819, 1831, 1872, 1899, 1937, 1990, 2034, 47, 62, + 93, 102, 122, 153, 185, 195, 282, 291, 312, 362, 369, 432, 468, 540, 599, 600, 611, 715, 747, 840, 857, 912, 1037, + 1052, 1112, 1126, 1219, 1321, 1359, 1372, 1419, 1424, 1451, 1568, 1623, 1635, 1672, 1691, 1701, 1704, 1723, 1796, + 1958, 1994, 2011, 2026, 2043, 31, 61, 91, 121, 181, 197, 202, 234, 241, 281, 293, 308, 331, 361, 370, 481, 538, + 568, 613, 695, 711, 738, 755, 781, 787, 995, 1080, 1118, 1178, 1188, 1210, 1380, 1400, 1427, 1473, 1498, 1530, + 1550, 1557, 1600, 1617, 1668, 1719, 1735, 1762, 1779, 1814, 1834, 1843, 1877, 1889, 1935, 1967, 1993, 2025, 2039, + 59, 117, 167, 182, 198, 201, 233, 242, 294, 327, 387, 465, 482, 559, 564, 605, 624, 662, 722, 740, 803, 852, 864, + 881, 907, 917, 939, 962, 979, 997, 1049, 1071, 1086, 1146, 1191, 1206, 1222, 1266, 1301, 1324, 1369, 1383, 1406, + 1422, 1441, 1454, 1480, 1512, 1526, 1549, 1686, 1713, 1739, 1746, 1771, 1808, 1833, 1871, 1970, 1989, 2006, 2016, + 2033, 118, 305, 334, 364, 389, 394, 404, 426, 466, 484, 543, 550, 573, 586, 603, 616, 633, 654, 686, 717, 749, 793, + 805, 843, 873, 903, 930, 964, 1008, 1055, 1115, 1128, 1142, 1200, 1226, 1258, 1293, 1308, 1375, 1476, 1520, 1562, + 1574, 1680, 1824 }; + +static int cbest_12[1023] = { + 1, 2, 2089, 4, 8, 3133, 16, 2088, 1044, 3, 32, 522, 261, 3639, 5, 64, 65, 2057, 2091, 6, 130, 3132, 260, + 2219, 9, 2093, 3117, 10, 128, 257, 2081, 3890, 12, 1566, 2217, 3129, 17, 514, 520, 3135, 18, 3196, 3637, 20, + 256, 1028, 1045, 3638, 24, 33, 523, 783, 2105, 3197, 3647, 34, 1040, 1945, 2056, 2090, 2595, 3125, 3891, 36, + 1046, 2348, 40, 1598, 2218, 3635, 7, 48, 66, 67, 131, 263, 269, 512, 538, 782, 1076, 1174, 1819, 2049, 2059, + 2092, 2152, 3113, 3116, 3384, 3607, 3888, 68, 69, 277, 554, 1108, 1109, 1558, 1564, 1944, 2061, 2080, 2478, + 3894, 72, 73, 134, 265, 293, 391, 526, 586, 587, 779, 2153, 2211, 2216, 2563, 3128, 4016, 11, 14, 80, 81, + 129, 132, 138, 530, 1172, 1692, 2073, 2095, 2223, 2316, 3101, 3109, 3119, 3134, 3645, 3874, 13, 96, 97, 146, + 259, 262, 268, 289, 799, 1052, 1060, 1158, 1567, 1818, 2083, 2221, 2344, 2349, 2476, 2980, 3045, 3192, 3368, + 3636, 144, 162, 276, 389, 515, 521, 578, 579, 781, 972, 1024, 1156, 2085, 2120, 2235, 2282, 2312, 3131, 3623, + 19, 22, 28, 160, 194, 195, 264, 292, 390, 778, 846, 1238, 1239, 1562, 1596, 1684, 1937, 1947, 2104, 2233, + 2593, 3193, 3385, 3633, 3643, 3646, 3889, 21, 26, 324, 518, 536, 909, 1029, 1297, 2008, 2121, 2209, 2283, + 2479, 2594, 2854, 3085, 3121, 3124, 3188, 3198, 3605, 3895, 25, 136, 258, 288, 528, 552, 798, 842, 1030, + 1140, 1141, 1490, 1556, 2470, 2603, 2626, 2721, 3892, 3898, 4017, 35, 38, 44, 56, 320, 388, 423, 486, 524, + 570, 584, 585, 618, 619, 648, 777, 780, 1041, 1594, 1817, 2097, 2107, 2317, 2561, 3105, 3164, 3189, 3199, + 3263, 3634, 3875, 37, 42, 52, 285, 309, 421, 1036, 1042, 1047, 1056, 1072, 1170, 1313, 1427, 1823, 1936, + 1946, 2048, 2053, 2058, 2065, 2109, 2280, 2345, 2477, 2579, 2627, 2981, 3041, 3044, 3112, 3127, 3369, 3388, + 3603, 3606, 3631, 3765, 3872, 41, 192, 193, 273, 399, 775, 797, 908, 968, 1104, 1105, 1168, 1236, 1237, 1281, + 1296, 1554, 1582, 1599, 1949, 2051, 2060, 2313, 2332, 2340, 2474, 3115, 3165, 3336, 3360, 3641, 4018, 49, 70, + 71, 76, 77, 88, 89, 112, 113, 387, 454, 484, 513, 516, 539, 640, 744, 745, 1004, 1077, 1175, 1234, 1235, + 1550, 1668, 1680, 1694, 1803, 2063, 2112, 2210, 2215, 2227, 2281, 2472, 2562, 2784, 3261, 3449, 3547, 3591, + 3621, 84, 85, 104, 105, 142, 154, 178, 226, 227, 242, 243, 267, 271, 385, 422, 534, 555, 771, 776, 791, 834, + 840, 844, 973, 1068, 1078, 1166, 1425, 1488, 1559, 1560, 1565, 1688, 1816, 2072, 2077, 2094, 2136, 2144, + 2154, 2222, 2298, 2336, 2350, 2468, 2543, 2611, 2624, 2658, 2729, 2850, 2855, 2982, 3081, 3097, 3100, 3108, + 3118, 3184, 3247, 3326, 3376, 3644, 3702, 4024, 82, 83, 135, 164, 170, 210, 211, 279, 284, 308, 328, 356, + 372, 417, 420, 527, 542, 576, 577, 616, 617, 656, 795, 847, 1048, 1110, 1111, 1312, 1329, 1392, 1426, 1590, + 1592, 1822, 2082, 2113, 2128, 2156, 2187, 2220, 2364, 2466, 2471, 2785, 2976, 3077, 3111, 3180, 3245, 3882, + 3893, 3899, 3902, 4081, 15, 30, 50, 60, 98, 99, 120, 121, 133, 139, 166, 272, 291, 295, 325, 340, 398, 419, + 531, 558, 582, 583, 712, 713, 774, 796, 838, 1064, 1084, 1173, 1182, 1232, 1233, 1280, 1522, 1542, 1676, + 1693, 1811, 1948, 2009, 2084, 2137, 2145, 2155, 2185, 2213, 2225, 2234, 2286, 2299, 2599, 2601, 2625, 2659, + 2745, 2870, 2988, 3047, 3130, 3185, 3194, 3327, 3352, 3386, 3545, 3601, 3619, 3622, 3629, 3703, 3733, 3773, + 3896, 3955, 140, 147, 152, 176, 186, 198, 199, 224, 225, 281, 305, 332, 386, 397, 532, 546, 590, 591, 680, + 696, 843, 901, 911, 974, 1026, 1032, 1053, 1061, 1116, 1117, 1159, 1164, 1491, 1552, 1802, 1941, 2069, 2087, + 2122, 2129, 2157, 2168, 2232, 2296, 2314, 2318, 2446, 2567, 2592, 2737, 2852, 3040, 3073, 3093, 3103, 3156, + 3181, 3389, 3627, 3632, 3642, 3858, 3873, 4020, 74, 75, 145, 163, 168, 208, 209, 266, 270, 321, 384, 395, + 452, 487, 502, 664, 770, 790, 905, 1025, 1054, 1148, 1149, 1152, 1157, 1301, 1360, 1424, 1578, 1686, 1821, + 1851, 1929, 1939, 2012, 2208, 2287, 2328, 2333, 2341, 2346, 2381, 2397, 2444, 2464, 2475, 2723, 2752, 3084, + 3120, 3195, 3337, 3361, 3370, 3417, 3514, 3579, 3604, 3615, 3780, 3878, 3984, 4019, 23, 29, 46, 92, 93, 161, + 240, 241, 278, 348, 416, 450, 562, 568, 610, 611, 650, 769, 773, 789, 794, 1154, 1222, 1223, 1328, 1376, + 1494, 1520, 1563, 1597, 1685, 1951, 2010, 2075, 2123, 2169, 2284, 2297, 2473, 2511, 2541, 2602, 2619, 2666, + 2720, 3107, 3123, 3157, 3294, 3324, 3372, 3448, 3453, 3546, 3587, 3670, 3710, 27, 196, 197, 290, 294, 418, + 482, 519, 537, 540, 574, 688, 787, 793, 969, 1062, 1142, 1143, 1435, 1548, 1588, 1662, 1663, 1801, 1810, + 1992, 2055, 2096, 2101, 2106, 2337, 2351, 2469, 2539, 2542, 2560, 2571, 2577, 2634, 2753, 2851, 2919, 2983, + 3013, 3043, 3104, 3259, 3262, 3322, 3377, 3380, 3441, 3625, 3717, 3767, 3781, 3880, 3900, 3939, 4025, 4049, + 137, 174, 280, 304, 322, 326, 344, 352, 393, 396, 455, 480, 485, 529, 553, 556, 760, 761, 832, 900, 910, 964, + 970, 1005, 1031, 1124, 1125, 1180, 1289, 1317, 1333, 1540, 1557, 1574, 1580, 1586, 1690, 1724, 1921, 1940, + 2052, 2064, 2099, 2108, 2250, 2266, 2285, 2304, 2365, 2467, 2578, 2583, 2609, 2656, 2667, 2848, 2977, 2996, + 3126, 3166, 3176, 3215, 3239, 3257, 3295, 3325, 3512, 3602, 3617, 3630, 3671, 3700, 3711, 3761, 3764, 3842, + 3883, 3903, 4080, 39, 45, 57, 148, 172, 184, 287, 297, 336, 394, 448, 525, 544, 571, 588, 589, 649, 746, 747, + 835, 841, 845, 904, 996, 1006, 1038, 1074, 1080, 1092, 1093, 1178, 1220, 1221, 1300, 1489, 1492, 1538, 1595, + 1670, 1682, 1756, 1757, 1795, 1815, 1820, 1835, 1850, 1928, 1938, 2050, 2111, 2179, 2356, 2440, 2509, 2565, + 2587, 2635, 2871, 2915, 2978, 2984, 2989, 3046, 3053, 3114, 3148, 3172, 3207, 3292, 3323, 3340, 3353, 3356, + 3364, 3387, 3401, 3445, 3544, 3589, 3640, 3729, 3757, 3769, 3796, 3897, 3954, 3959, 251, 373, 581, 1057, + 1107, 1137, 1299, 1630, 1882, 2214, 2308, 2315, 2319, 2597, 2853, 3167, 3260, 3482, 3590, 3862 }; + +static int cbest_13[1023] = { + 1, 2, 4109, 4, 6155, 8, 7176, 16, 3588, 4108, 32, 2054, 3, 1027, 1794, 6, 64, 4620, 6154, 5, 897, 4111, 6153, + 7177, 12, 2310, 3077, 4105, 128, 9, 24, 513, 1155, 10, 1026, 4101, 7689, 18, 48, 256, 896, 3589, 4365, 6159, + 7178, 17, 448, 4557, 4621, 4684, 5647, 36, 96, 224, 1025, 1792, 20, 112, 512, 769, 1538, 1795, 2052, 3076, + 3590, 6147, 6283, 7180, 33, 56, 72, 192, 2055, 2342, 3584, 4125, 6411, 7945, 28, 34, 577, 1154, 6922, 7240, + 14, 144, 384, 2050, 4110, 4493, 5134, 5903, 6152, 7168, 7304, 7, 40, 65, 1171, 3620, 4104, 4141, 5004, 288, + 768, 1153, 2308, 2567, 3652, 4097, 4107, 4397, 4685, 6157, 6171, 6379, 7688, 13, 68, 1024, 1810, 2311, 3461, + 4676, 7179, 66, 129, 576, 1826, 3079, 3844, 4100, 4173, 4622, 5646, 6347, 8073, 25, 80, 899, 905, 1031, 1091, + 1798, 2182, 2306, 2338, 2502, 3073, 3596, 4364, 4616, 5390, 5645, 6158, 6187, 7050, 7192, 11, 26, 913, 1922, + 4117, 4556, 4652, 5262, 6151, 6299, 6443, 6923, 7181, 19, 49, 130, 136, 257, 1169, 1283, 1536, 1793, 2062, + 2326, 2566, 2823, 4103, 4237, 6145, 7182, 7232, 7272, 7691, 7944, 50, 449, 515, 901, 961, 1035, 1163, 1170, + 1539, 1802, 2048, 2340, 2695, 3586, 3591, 3604, 3616, 4553, 4612, 4680, 4748, 5005, 6146, 6219, 6282, 7208, + 7241, 7288, 22, 37, 52, 97, 160, 225, 585, 1152, 1251, 1808, 2374, 2631, 3141, 3585, 4124, 4549, 4876, 5135, + 5902, 6281, 6410, 7169, 7172, 7305, 7320, 7560, 21, 38, 98, 113, 132, 226, 258, 452, 545, 898, 904, 1187, + 2053, 2070, 2278, 2438, 3205, 3460, 3525, 3636, 3972, 4127, 4137, 4157, 4367, 4677, 5132, 5839, 5901, 6163, + 6169, 6409, 6666, 7693, 57, 73, 100, 114, 193, 228, 272, 450, 456, 517, 912, 1029, 1043, 1159, 1219, 1796, + 2343, 3078, 3333, 4113, 4121, 4361, 4381, 4393, 4492, 4559, 4623, 4686, 5518, 6275, 6920, 7721, 8137, 29, 35, + 44, 74, 104, 146, 641, 1030, 1090, 1730, 1824, 2246, 2318, 2822, 3072, 3085, 3592, 3621, 3660, 3780, 4099, + 4140, 4149, 4165, 4205, 4333, 4617, 4700, 5454, 5643, 6149, 6377, 7051, 7170, 7244, 7753, 7947, 15, 30, 42, + 60, 76, 120, 145, 196, 240, 260, 292, 320, 385, 480, 514, 771, 900, 960, 1123, 1411, 1818, 1986, 2051, 2086, + 2304, 2694, 2951, 3622, 3648, 3653, 4096, 4106, 4221, 4396, 4429, 4589, 4636, 4653, 4716, 5422, 5679, 6156, + 6170, 6378, 6603, 7184, 7242, 7681, 8072, 41, 58, 194, 200, 521, 581, 584, 785, 865, 1059, 1139, 1168, 1282, + 1347, 1811, 2058, 2198, 2350, 2565, 2630, 3644, 4301, 4357, 4485, 4732, 5391, 5644, 5711, 6191, 6203, 6287, + 6297, 7193, 7296, 7306, 70, 88, 148, 208, 289, 544, 579, 801, 1034, 1089, 1099, 1162, 1315, 1570, 1827, 1830, + 1890, 2309, 2324, 2336, 2358, 2759, 3075, 3093, 3845, 4133, 4143, 4172, 4613, 4648, 4668, 4681, 4749, 4812, + 4996, 5263, 5278, 5388, 5639, 5775, 6167, 6175, 6185, 6315, 6346, 6383, 6415, 6427, 6447, 7194, 7949, 7961, + 69, 84, 116, 152, 264, 290, 386, 392, 516, 593, 773, 833, 909, 993, 1033, 1161, 1175, 1250, 1542, 1602, 1799, + 1800, 1920, 2118, 2498, 2727, 3140, 3597, 3654, 4253, 4389, 4399, 4495, 4672, 4780, 4877, 5260, 6186, 6195, + 6211, 6251, 6345, 6441, 6794, 6926, 6938, 7018, 7183, 7233, 7256, 7273, 7624, 7690, 7977, 67, 82, 400, 529, + 609, 640, 929, 1041, 1157, 1179, 1186, 1249, 1281, 1666, 1858, 1923, 2060, 2180, 2334, 2406, 2500, 2563, + 2711, 3173, 3204, 3463, 3524, 3598, 3628, 3716, 4036, 4116, 4169, 4489, 4509, 4608, 4618, 4660, 4678, 4764, + 5006, 5130, 5899, 5919, 6150, 6267, 6298, 6351, 6442, 6475, 6667, 6730, 6954, 7048, 7174, 7209, 7212, 7224, + 7289, 7308, 7400, 7432, 81, 140, 176, 232, 296, 416, 625, 770, 915, 945, 1028, 1042, 1158, 1185, 1218, 1537, + 1814, 2068, 2183, 2307, 2322, 2339, 2390, 2503, 2950, 3109, 3189, 3332, 3397, 3457, 3606, 3612, 3846, 4102, + 4236, 4525, 4687, 5000, 5020, 5582, 5641, 5871, 5935, 6144, 6339, 6403, 6539, 6921, 6986, 7173, 7188, 7196, + 7321, 7336, 7561, 7705, 7937, 8065, 8075, 27, 54, 108, 168, 216, 304, 388, 432, 520, 561, 580, 705, 777, 784, + 864, 907, 1039, 1167, 1203, 1546, 1803, 1806, 2314, 2366, 2382, 2564, 2639, 2821, 3081, 3084, 3149, 3221, + 3365, 3469, 3587, 3600, 3605, 3617, 3668, 3840, 4373, 4413, 4541, 4552, 4701, 5133, 5198, 5838, 5900, 6179, + 6218, 6303, 6395, 6914, 7042, 7216, 7234, 7274, 7322, 7368, 7692, 8169, 131, 137, 164, 464, 578, 673, 800, + 903, 1095, 1122, 1195, 1410, 1475, 1762, 1809, 1822, 1834, 2056, 2063, 2078, 2082, 2178, 2276, 2327, 2330, + 2370, 2599, 2627, 2693, 2758, 3137, 3477, 3594, 3618, 3684, 3812, 4119, 4175, 4548, 4555, 4573, 4637, 4644, + 4654, 4682, 4692, 4717, 5068, 5126, 5254, 5446, 5486, 5519, 5663, 5837, 5895, 6031, 6161, 6217, 6279, 6280, + 6291, 6435, 7210, 7236, 7276, 7290, 7695, 7720, 7725, 7737, 7745, 8136, 51, 138, 280, 352, 549, 592, 657, + 772, 832, 908, 917, 992, 1051, 1058, 1121, 1138, 1191, 1217, 1346, 1816, 1842, 2018, 2049, 2066, 2190, 2274, + 2341, 2346, 2372, 2510, 2629, 2726, 3493, 3521, 3608, 3632, 3637, 3700, 3860, 3973, 4126, 4136, 4156, 4189, + 4229, 4366, 4405, 4421, 4461, 4628, 4696, 4733, 5276, 5420, 5455, 5470, 5516, 5642, 5677, 6162, 6168, 6223, + 6273, 6363, 6408, 7171, 7245, 7264, 7752, 7946, 8077, 8089, 23, 53, 134, 161, 336, 454, 496, 528, 608, 921, + 928, 1057, 1088, 1098, 1107, 1137, 1173, 1314, 1379, 1540, 1554, 1728, 1797, 1930, 2102, 2196, 2316, 2348, + 2375, 2436, 2562, 2710, 2819, 3074, 3092, 3509, 3638, 3876, 4112, 4120, 4360, 4380, 4392, 4445, 4545, 4558, + 4565, 4605, 4614, 4649, 4669, 4740, 4813, 4997, 5386, 5406, 5418, 5423, 5452, 5675, 5678, 5695, 5703, 6274, + 6285, 6371, 6664, 7054, 7066, 7185, 7200, 7243, 7246, 7280, 7324, 7680, 7685, 7729, 7881, 39, 78, 133, 156, + 162, 227, 274, 312, 328, 453, 519, 569, 624, 914, 965, 1032, 1037, 1075, 1097, 1165, 1313, 1363, 1409, 1825, + 1828, 1938, 2074, 2084, 2214, 2242, 2279, 2439, 2534, 2691, 3143, 3593, 3650, 3656, 3661, 3781, 4123, 4148, + 4153, 4239, 4353, 4363, 4481, 4551, 4673, 4781, 5128, 5258, 5358, 5637, 5710, 5807, 5835, 5897, 5917, 6173, + 6355, 6413, 6419, 6425, 6459, 6795, 6858, 6927, 7019, 7297, 7300, 7307, 7312, 7562, 7723, 7953 }; + +static int cbest_14[1023] = { + 1, 2, 8737, 4, 8, 13105, 16, 8736, 32, 4368, 3, 2184, 17, 1092, 15289, 34, 546, 5, 64, 68, 273, 8739, 8745, + 6, 136, 13104, 272, 9, 8741, 128, 8873, 12, 6552, 13109, 10, 544, 13107, 256, 18, 24, 3276, 8753, 33, 1088, + 4369, 15288, 16381, 2185, 8705, 13089, 13173, 20, 512, 1093, 2186, 4372, 8195, 8738, 8744, 13113, 35, 66, + 547, 1094, 1638, 2188, 4370, 4376, 8752, 8865, 12832, 15291, 36, 48, 65, 69, 257, 2176, 6416, 8707, 10921, 7, + 19, 25, 70, 137, 3208, 8740, 9008, 9829, 13088, 13169, 15281, 96, 132, 138, 277, 554, 1024, 1108, 1604, 6544, + 8749, 8872, 50, 140, 275, 281, 562, 802, 819, 3272, 4504, 7644, 8747, 8801, 8805, 12833, 13073, 13108, 21, + 100, 129, 192, 276, 401, 1636, 4352, 4436, 8743, 12563, 13106, 15257, 15293, 13, 38, 40, 72, 130, 200, 264, + 274, 280, 514, 550, 818, 2216, 2252, 6553, 8193, 8875, 9009, 15259, 11, 14, 49, 384, 400, 545, 1124, 2048, + 2218, 6554, 8761, 8877, 13075, 13111, 15273, 409, 1100, 1126, 14197, 15153, 15839, 42, 528, 768, 1109, 4097, + 4432, 8937, 9144, 15016, 16377, 16380, 51, 76, 98, 102, 204, 408, 552, 563, 803, 1090, 2200, 2248, 3277, + 8203, 8704, 10785, 13172, 144, 260, 548, 560, 800, 817, 1028, 1089, 1536, 3822, 4096, 4353, 8194, 8760, + 13112, 13117, 13241, 15272, 16365, 28, 258, 265, 1606, 1634, 4380, 6556, 8864, 8869, 8993, 9136, 10913, + 12561, 12836, 15290, 26, 80, 84, 196, 385, 513, 816, 1056, 2180, 2187, 2190, 3072, 3268, 3278, 4373, 4400, + 4496, 6145, 7508, 8706, 8755, 8941, 9016, 9145, 9287, 10920, 12013, 12290, 13175, 15017, 22, 67, 152, 1095, + 1639, 2189, 3212, 3292, 4371, 4374, 4377, 4568, 4572, 6418, 6536, 6584, 8225, 8929, 9825, 9828, 12849, 13093, + 13141, 13168, 13233, 14129, 14747, 15280, 16373, 16383, 37, 529, 570, 769, 1104, 1600, 1632, 2177, 5460, + 6144, 6417, 6586, 7636, 8466, 8713, 8748, 8867, 13091, 13097, 13171, 15837, 16313, 16364, 71, 134, 168, 285, + 392, 520, 530, 770, 1026, 1058, 1096, 2056, 2178, 2201, 2284, 3209, 4233, 4360, 4402, 4508, 4914, 6424, 7640, + 8709, 8721, 8746, 8757, 8800, 8804, 8992, 9121, 9137, 10923, 11809, 12837, 13072, 13115, 13137, 14193, 15566, + 97, 133, 139, 142, 145, 261, 288, 305, 337, 555, 561, 785, 801, 1025, 1120, 1140, 1605, 1646, 2112, 2116, + 2730, 3210, 3264, 3754, 4378, 6420, 6545, 8201, 8211, 8451, 8742, 8754, 8803, 8809, 8841, 8889, 9001, 9017, + 9831, 10925, 12291, 12562, 12834, 12840, 15161, 15256, 15283, 15292, 29, 56, 141, 259, 268, 279, 284, 674, + 1110, 1142, 1538, 1570, 1911, 2280, 2457, 3273, 3820, 4232, 4505, 6281, 6546, 7628, 7645, 8192, 8715, 8751, + 8769, 8874, 9012, 9285, 9317, 12848, 12960, 13057, 13077, 13092, 14880, 15258, 15265, 15285, 15295, 27, 52, + 74, 81, 85, 101, 160, 193, 304, 336, 516, 558, 784, 1060, 1348, 1365, 1540, 1637, 2052, 2254, 2286, 3140, + 3200, 3274, 3818, 4225, 4437, 4506, 4560, 6480, 6528, 6548, 7440, 8190, 8199, 8467, 8723, 8807, 8876, 9010, + 9129, 9837, 11945, 12307, 12547, 13074, 13090, 13096, 13110, 13143, 13655, 14745, 14777, 15241, 15353, 15357, + 15831, 23, 39, 41, 44, 73, 131, 153, 194, 201, 278, 290, 307, 403, 515, 536, 551, 610, 614, 806, 823, 1116, + 1122, 1228, 1612, 1910, 2050, 2217, 2220, 2253, 2456, 2696, 3224, 3240, 3293, 3720, 4105, 4438, 6280, 6537, + 8331, 8720, 8756, 8773, 8879, 8881, 9120, 9761, 9845, 10849, 10853, 12288, 12593, 13157, 13297, 13617, 14196, + 15008, 15152, 15243, 15567, 15835, 15838, 16245, 15, 58, 112, 170, 202, 283, 341, 405, 571, 682, 810, 1040, + 1105, 1125, 1364, 1568, 1620, 1860, 1877, 2049, 2192, 2219, 2250, 3076, 4101, 4112, 4224, 4356, 4500, 5392, + 6448, 6555, 7504, 7646, 8210, 8227, 8450, 8711, 8813, 8888, 8936, 9000, 10889, 12009, 12567, 12835, 12841, + 12968, 13059, 13177, 13181, 13305, 13309, 14888, 15155, 16108, 16376, 104, 306, 386, 393, 402, 531, 568, 771, + 822, 930, 1030, 1101, 1127, 1602, 1644, 2120, 2728, 3080, 3288, 3752, 3814, 4104, 4354, 4361, 4434, 4440, + 4444, 6153, 7576, 8202, 8219, 8464, 8602, 8843, 8933, 9013, 9797, 10784, 10789, 10891, 11877, 12571, 12896, + 12900, 12961, 13056, 13237, 14097, 14181, 14474, 14881, 15249, 15264, 15275, 16357, 16369, 43, 116, 148, 224, + 266, 282, 289, 340, 388, 404, 411, 465, 522, 576, 580, 608, 672, 1072, 1102, 1141, 1220, 1876, 1909, 2208, + 2222, 2240, 2244, 2282, 3136, 4100, 4433, 4468, 4564, 4912, 5456, 6273, 6400, 6484, 7444, 7620, 7632, 8323, + 8722, 8765, 9011, 9128, 9799, 9965, 10787, 10989, 12306, 12546, 13079, 13116, 13139, 13240, 13245, 14199, + 15033, 15240, 15251, 15261, 15564, 15869, 16317, 16361, 54, 57, 77, 99, 103, 162, 205, 232, 269, 518, 553, + 556, 566, 787, 1062, 1091, 1111, 1143, 1542, 2060, 2210, 2232, 2249, 3788, 3816, 6152, 6450, 7629, 7783, + 8182, 8197, 8209, 8241, 8449, 8481, 8587, 8763, 8868, 8880, 8939, 9146, 9295, 9844, 10912, 10917, 11471, + 11813, 12005, 12289, 12560, 13153, 13156, 13301, 13653, 13685, 15009, 15018, 15157, 15242, 15562, 16379, 46, + 53, 78, 208, 320, 410, 448, 464, 549, 612, 772, 804, 821, 938, 955, 1029, 1349, 1537, 1642, 1908, 2202, 2234, + 3242, 3284, 3722, 3823, 4240, 4464, 6160, 6272, 6529, 6558, 6576, 7098, 7237, 8233, 8329, 8771, 8775, 8871, + 8905, 8940, 9020, 9283, 9286, 10793, 12012, 12294, 12844, 12857, 12969, 13058, 13174, 13587, 14099, 14521, + 14739, 14761, 14889, 15020, 15321, 15430, 15833, 16109, 16349, 82, 88, 146, 262, 291, 537, 578, 680, 776, + 786, 807, 1032, 1074, 1117, 1160, 1574, 1607, 1635, 1654, 1894, 1907, 2124, 2182, 2204, 2440, 3084, 3225, + 3308, 3810, 4099, 4120, 4301, 4381, 4488, 4643, 6147, 6557, 6578, 6616, 6620, 7782, 8188, 8207, 8218, 8224, + 8465, 8603, 8833, 8928, 9249, 9824, 11873, 12305, 12337, 12545, 12565, 12577, 12853, 12897, 12901, 12977, + 13119, 13140, 13232, 13243, 14128, 14133, 14180, 14475, 14746, 15121, 15217, 15263, 15274, 15771, 15829, + 16177, 16356, 16372, 16382, 30, 59, 113, 197, 206, 469, 811, 820, 827, 896, 928, 954, 1041, 1057, 1136, 1216, + 1344, 1361, 1572, 1621, 1861, 2080, 2144, 2181, 2193, 2321, 3073, 3204, 3214, 3269, 3279, 4113, 4357, 4384, + 4404, 4420, 4497, 4922, 7236, 7492, 7509, 8579, 8600, 8712, 8729, 8866, 9138, 9319, 9827, 9833, 10915, 10985, + 11267, 12595, 12631, 12838, 13101, 13170, 13382, 13619, 13651, 14131, 14472, 14504, 15032, 15325, 15565, + 15827, 16125, 16312 }; + +static int cbest_15[1023] = { + 1, 2, 16385, 4, 8, 24577, 16, 32, 64, 28673, 128, 256, 512, 1024, 30721, 2048, 4096, 8192, 16384, 31745, 3, + 6, 12, 24, 48, 96, 192, 384, 768, 1536, 3072, 6144, 12288, 24576, 5, 16387, 9, 16389, 10, 17, 16393, 24579, + 28672, 18, 33, 14336, 16401, 24581, 20, 34, 65, 7168, 16417, 24585, 32257, 36, 66, 129, 3584, 16449, 24593, + 28675, 40, 68, 130, 257, 1792, 16513, 24609, 28677, 30720, 72, 132, 258, 513, 896, 16641, 24641, 28681, 80, + 136, 260, 448, 514, 1025, 15360, 16897, 24705, 28689, 144, 224, 264, 516, 1026, 2049, 17409, 24833, 28705, + 30723, 112, 160, 272, 520, 1028, 2050, 4097, 7680, 18433, 25089, 28737, 30725, 56, 288, 528, 1032, 2052, + 4098, 8193, 20481, 25601, 28801, 30729, 31744, 32513, 28, 320, 544, 1040, 2056, 3840, 4100, 8194, 26625, + 28929, 30737, 14, 576, 1056, 2064, 4104, 8196, 16386, 29185, 30753, 7, 13, 25, 49, 97, 193, 385, 640, 769, + 1088, 1537, 1920, 2080, 3073, 4112, 6145, 8200, 12289, 15872, 16388, 29697, 30785, 31747, 26, 50, 98, 194, + 386, 770, 1152, 1538, 2112, 3074, 4128, 6146, 8208, 12290, 16391, 16392, 16397, 16409, 16433, 16481, 16577, + 16769, 17153, 17921, 19457, 22529, 24578, 30849, 31749, 52, 100, 196, 388, 772, 960, 1280, 1540, 2176, 3076, + 4160, 6148, 8224, 12292, 16400, 24580, 30977, 31753, 11, 104, 200, 392, 776, 1544, 2304, 3080, 4224, 6152, + 7936, 8256, 12296, 16416, 24583, 24584, 24589, 24601, 24625, 24673, 24769, 24961, 25345, 26113, 27649, 31233, + 31761, 32256, 19, 22, 208, 400, 480, 784, 1552, 2560, 3088, 4352, 6160, 8320, 12304, 14337, 16395, 16448, + 24592, 28674, 31777, 21, 35, 38, 44, 416, 800, 1568, 3104, 4608, 6176, 7169, 8448, 12320, 14338, 16403, + 16512, 24608, 28676, 31809, 32641, 37, 67, 70, 76, 88, 240, 832, 1600, 3136, 3585, 3968, 5120, 6208, 7170, + 8704, 12352, 14340, 16405, 16419, 16640, 23553, 24587, 24640, 28679, 28680, 28685, 28697, 28721, 28769, + 28865, 29057, 29441, 30209, 31873, 32259, 41, 69, 131, 134, 140, 152, 176, 1664, 1793, 3200, 3586, 6272, + 7172, 9216, 12416, 14344, 16128, 16421, 16451, 16896, 19969, 24595, 24704, 28688, 32001, 32261, 42, 73, 120, + 133, 259, 262, 268, 280, 304, 352, 897, 1794, 3328, 3588, 6400, 7176, 10240, 12544, 14352, 16425, 16453, + 16515, 17408, 18177, 24597, 24611, 24832, 28704, 30722, 32265, 74, 81, 137, 261, 449, 515, 518, 524, 536, + 560, 608, 704, 898, 1796, 1984, 3592, 6656, 7184, 12800, 14368, 15361, 16457, 16517, 16643, 17281, 18432, + 24613, 24643, 25088, 28161, 28683, 28736, 30724, 32273, 60, 82, 138, 145, 225, 265, 450, 517, 900, 1027, + 1030, 1036, 1048, 1072, 1120, 1216, 1408, 1800, 3600, 7200, 13312, 14400, 15362, 16465, 16521, 16645, 16833, + 16899, 20480, 24617, 24645, 24707, 25600, 26369, 28691, 28800, 30727, 30728, 30733, 30745, 30769, 30817, + 30913, 31105, 31489, 32289, 32512, 84, 113, 146, 161, 226, 266, 273, 452, 521, 904, 1029, 1808, 2051, 2054, + 2060, 2072, 2096, 2144, 2240, 2432, 2816, 3616, 7232, 7681, 8064, 14464, 15364, 16529, 16609, 16649, 16901, + 17411, 24649, 24709, 24835, 25473, 26624, 28693, 28707, 28928, 30736, 32321, 30, 57, 114, 148, 162, 228, 274, + 289, 456, 522, 529, 912, 992, 1033, 1824, 2053, 3648, 4099, 4102, 4108, 4120, 4144, 4192, 4288, 4480, 4864, + 5632, 7296, 7682, 14592, 15368, 16497, 16545, 16657, 16905, 17413, 18435, 24065, 24657, 24713, 24837, 25025, + 25091, 28709, 28739, 29184, 30752, 32385, 29, 58, 116, 164, 232, 276, 290, 321, 464, 530, 545, 928, 1034, + 1041, 1856, 2057, 3712, 3841, 4101, 7424, 7684, 8195, 8198, 8204, 8216, 8240, 8288, 8384, 8576, 8960, 9728, + 11264, 14848, 15376, 16441, 16673, 16913, 17417, 18437, 20483, 24721, 24801, 24841, 25093, 25603, 28713, + 28741, 28803, 29696, 30465, 30731, 30784, 31746, 32515, 15, 168, 292, 322, 532, 546, 577, 1042, 1057, 2058, + 2065, 3842, 4105, 7688, 8197, 15392, 16390, 16396, 16408, 16413, 16432, 16480, 16576, 16705, 16768, 16929, + 17152, 17425, 17920, 18441, 19456, 20225, 20485, 22528, 24689, 24737, 24849, 25097, 25605, 26627, 28745, + 28805, 28931, 29569, 30739, 30848, 31748, 32517, 32705, 296, 324, 496, 548, 578, 641, 1044, 1058, 1089, 1921, + 2066, 2081, 3844, 4032, 4106, 4113, 7696, 8201, 15424, 15873, 16256, 16399, 16961, 17441, 18449, 20489, + 24633, 24865, 25105, 25609, 26629, 28753, 28809, 28933, 29121, 29187, 30741, 30755, 30976, 31751, 31752, + 31757, 31769, 31793, 31841, 31937, 32129, 32521, 27, 51, 54, 99, 102, 108, 195, 198, 204, 216, 328, 387, 390, + 396, 408, 432, 552, 580, 642, 771, 774, 780, 792, 816, 864, 1060, 1090, 1153, 1539, 1542, 1548, 1560, 1584, + 1632, 1728, 1922, 2068, 2082, 2113, 3075, 3078, 3084, 3096, 3120, 3168, 3264, 3456, 3848, 4114, 4129, 6147, + 6150, 6156, 6168, 6192, 6240, 6336, 6528, 6912, 7712, 8202, 8209, 12291, 12294, 12300, 12312, 12336, 12384, + 12480, 12672, 13056, 13824, 15488, 15874, 17025, 17473, 18305, 18465, 20497, 24582, 24588, 24600, 24605, + 24624, 24672, 24768, 24897, 24960, 25121, 25344, 25617, 26112, 26633, 27648, 28417, 28817, 28897, 28937, + 29189, 29699, 30757, 30787, 31232, 31760, 32529, 53, 101, 197, 336, 389, 584, 644, 773, 961, 1064, 1092, + 1154, 1281, 1541, 1924, 2084, 2114, 2177, 3077, 3856, 4116, 4130, 4161, 6149, 7744, 8210, 8225, 12293, 15616, + 15876, 16394, 16411, 16435, 16483, 16579, 16771, 17155, 17537, 17923, 18497, 19459, 20513, 22531, 24591, + 25153, 25633, 26641, 28785, 28833, 28945, 29193, 29701, 30761, 30789, 30851, 31776, 32545, 105, 201, 248, + 393, 592, 648, 777, 962, 1096, 1156, 1282, 1545, 1928, 2088, 2116, 2178, 2305, 3081, 3872, 4132, 4162, 4225, + 6153, 7808, 7937, 8212, 8226, 8257, 12297, 15880, 16402, 16437, 16485, 16581, 16773, 17157, 17345, 17665, + 17925, 18561, 19461, 20545, 22533, 25217, 25665, 26497, 26657, 28729, 28961, 29201, 29705, 30793, 30853, + 30979, 31617, 31755, 31808, 32577, 32640, 23, 46, 92, 106, 184, 202, 209, 368, 394, 401, 481, 656, 736, 778, + 785, 964, 1104, 1160, 1284, 1472, 1546, 1553, 1936, 2016, 2120, 2180, 2306, 2561, 2944, 3082, 3089, 3904, + 4136, 4164, 4226, 4353, 5888, 6154, 6161, 7938, 8228, 8258, 8321, 11776, 12298, 12305, 15888, 16404, 16418, + 16489, 16585, 16777, 17161, 17929, 18689, 19465, 20609, 22537, 23552, 24321, 24586, 24603, 24627, 24675, + 24771, 24963, 25347, 25729, 26115, 26689, 27651, 28678, 28684, 28696, 28701, 28720, 28768, 28864, 28993, + 29056, 29217, 29440, 29713, 30208, 30801, 30857, 30981, 31169, 31235, 31763, 31872, 32258, 45, 78, 156, 312, + 624, 672, 801, 1554, 2562, 14384, 16593, 16785, 17937, 24677, 31237, 31765 }; + +static int cbest_16[1023] = { + 1, 2, 34821, 4, 8, 52231, 16, 60934, 34820, 32, 17410, 3, 8705, 17, 34, 5, 68, 34823, 34829, 6, 136, 30467, + 34817, 39173, 52230, 64, 272, 52229, 9, 544, 52227, 10, 1088, 12, 2176, 26115, 4352, 50311, 60935, 18, 8704, + 45956, 60932, 20, 128, 24, 34837, 47876, 17408, 30466, 33, 36, 17411, 52239, 59974, 40, 22978, 48, 256, 8707, + 17414, 34822, 34828, 43524, 60930, 65286, 19, 35, 8709, 17418, 23938, 26114, 34816, 34836, 34853, 39172, + 52247, 21, 69, 15233, 21762, 30465, 34825, 52225, 52228, 7, 25, 38, 72, 137, 13057, 19586, 34831, 34881, + 52226, 42, 65, 80, 273, 10881, 26113, 29987, 34819, 34855, 39175, 50, 66, 70, 76, 545, 9793, 11489, 45957, + 60933, 60942, 11, 14, 84, 96, 138, 1089, 11969, 34957, 37253, 50310, 52261, 13, 152, 274, 1090, 2177, 34885, + 34949, 35093, 39169, 50309, 52246, 52263, 49, 144, 257, 546, 4353, 8713, 32643, 32901, 34845, 35365, 38341, + 47877, 60950, 22, 28, 140, 512, 2180, 4354, 25155, 30471, 35909, 40261, 45716, 52291, 52295, 100, 129, 160, + 276, 2178, 8706, 17426, 26123, 39717, 49351, 52235, 59975, 44, 98, 130, 168, 548, 4360, 8708, 8721, 34833, + 51271, 52237, 60928, 81, 132, 192, 304, 514, 1092, 15232, 30464, 30475, 34839, 34861, 39181, 43525, 45958, + 47872, 50307, 52238, 52367, 53703, 60931, 60951, 60966, 65287, 51, 88, 102, 204, 280, 408, 816, 1632, 3264, + 6528, 8720, 13056, 17409, 17412, 26119, 45952, 47396, 52243, 52503, 59972, 60964, 26, 37, 85, 170, 196, 288, + 340, 552, 680, 1360, 2720, 4356, 5440, 10880, 17416, 22858, 22976, 23936, 26112, 29986, 34844, 40565, 40805, + 52245, 52775, 54663, 41, 56, 153, 162, 200, 306, 612, 1096, 1224, 2448, 4896, 7616, 8737, 9792, 11488, 17422, + 17440, 21760, 22979, 30483, 34849, 34852, 39189, 47044, 47878, 49895, 50855, 59494, 60454, 65284, 145, 320, + 336, 1028, 2184, 8711, 11968, 17415, 17442, 34824, 34889, 34893, 43520, 50583, 52224, 60940, 60994, 23, 29, + 258, 392, 560, 608, 17419, 23698, 23939, 30482, 34827, 34830, 34832, 34863, 34880, 43526, 50319, 52259, + 56583, 60943, 64806, 46, 58, 74, 176, 260, 324, 384, 1024, 1104, 3808, 8225, 8712, 14993, 17427, 17474, + 19584, 21763, 32642, 34818, 34838, 34854, 39174, 45964, 52257, 57574, 59970, 39, 73, 82, 92, 264, 290, 2192, + 5744, 5984, 8769, 11429, 19587, 25154, 26131, 29985, 30227, 30470, 34869, 35077, 38933, 39205, 41604, 43532, + 52242, 52359, 58054, 60948, 61070, 63366, 65294, 43, 52, 112, 116, 400, 2056, 4368, 8739, 12577, 16450, + 17478, 20802, 21766, 26122, 29747, 30497, 34841, 34851, 34956, 37252, 42212, 50327, 52244, 52255, 52260, + 60998, 61206, 65282, 67, 71, 77, 89, 178, 184, 576, 672, 1904, 8773, 10401, 10883, 11425, 11849, 13061, + 15235, 15241, 17546, 18626, 22850, 22982, 26121, 26130, 30499, 34884, 34948, 34965, 35092, 39168, 39188, + 42692, 45700, 45717, 45972, 47884, 50191, 50308, 52233, 52262, 59014, 60938, 15, 27, 78, 97, 139, 148, 164, + 289, 352, 356, 1120, 1216, 2992, 8717, 8841, 9313, 13059, 13065, 17538, 17682, 19594, 23522, 30469, 30474, + 32900, 34857, 34883, 35364, 37013, 37249, 38340, 39171, 44612, 45836, 52293, 59906, 60246, 57, 86, 232, 275, + 640, 784, 1091, 2872, 8715, 8977, 9797, 17424, 17434, 17954, 23942, 26118, 26147, 29953, 32641, 34897, 34901, + 34945, 34981, 35908, 37255, 38221, 39233, 40260, 49349, 51127, 52290, 52294, 59766, 59982, 60110, 60929, + 60949, 154, 224, 321, 368, 547, 648, 712, 952, 4112, 4384, 9795, 11491, 15237, 16321, 17430, 22986, 25153, + 26117, 26145, 28787, 29027, 29955, 32403, 32897, 34871, 34887, 34951, 38337, 39207, 39716, 40533, 45596, + 45959, 47873, 47892, 49350, 51007, 51269, 52234, 52241, 52271, 52289, 52303, 60946, 60967, 104, 118, 141, + 156, 259, 328, 393, 513, 516, 561, 580, 704, 768, 800, 1496, 2181, 2208, 4355, 8725, 8736, 11393, 11457, + 11971, 19590, 21106, 21346, 22306, 22918, 29507, 30473, 30535, 34868, 34917, 34959, 35009, 35013, 35076, + 40021, 45701, 45953, 45973, 47397, 49231, 50305, 50341, 51270, 52236, 52269, 52279, 52311, 52487, 59973, + 60965, 30, 59, 101, 142, 161, 177, 186, 261, 277, 325, 385, 464, 520, 578, 786, 1105, 1344, 1424, 2179, 2182, + 4362, 8710, 8723, 10885, 17420, 19170, 20130, 23946, 24675, 25635, 29991, 30603, 31683, 32647, 34835, 34840, + 34860, 34909, 34953, 34973, 35095, 35101, 35911, 39180, 39309, 39477, 40517, 40549, 40737, 50306, 50326, + 50343, 52254, 52277, 52366, 53702, 59910, 59990, 60962, 61062, 45, 54, 83, 93, 99, 114, 131, 134, 146, 169, + 172, 194, 236, 265, 278, 291, 358, 476, 528, 549, 650, 736, 1094, 1122, 1436, 1572, 2048, 2193, 2240, 2432, + 2856, 4361, 8724, 8741, 11493, 17450, 17482, 19858, 21770, 22786, 22914, 22994, 30531, 32903, 32909, 34847, + 34913, 34964, 35089, 35367, 35373, 38343, 39183, 39237, 39719, 40535, 45988, 47045, 47879, 49827, 51267, + 52327, 52365, 52502, 53583, 53701, 54661, 59426, 59495, 60455, 60958, 65285, 53, 113, 117, 133, 193, 234, + 305, 308, 372, 448, 468, 515, 550, 582, 642, 716, 748, 936, 1093, 1152, 1300, 1408, 1428, 2210, 2848, 3144, + 4369, 8224, 8722, 11153, 11459, 11841, 11973, 14992, 17446, 17448, 22798, 25163, 26127, 30481, 34877, 34983, + 35333, 35361, 35917, 39177, 39685, 40263, 40564, 40804, 43521, 43540, 45236, 45476, 45580, 45718, 47636, + 47893, 49893, 50183, 50371, 50567, 50991, 52251, 52299, 52325, 52363, 52501, 52774, 53575, 54662, 60452, + 60941, 60947, 60995, 65302, 103, 166, 179, 185, 205, 281, 296, 312, 354, 370, 409, 472, 714, 740, 817, 928, + 1164, 1432, 1480, 1568, 1633, 1872, 2244, 2600, 3265, 4358, 4364, 4386, 5712, 6288, 6529, 8768, 8833, 9729, + 10065, 10673, 10889, 11397, 11428, 11761, 17413, 17444, 22790, 22856, 23682, 23954, 26183, 29713, 29984, + 29995, 30123, 30226, 34848, 34859, 34896, 34900, 35905, 40257, 43527, 45116, 45572, 45712, 45828, 46016, + 47156, 47392, 47874, 49894, 50854, 50983, 52307, 52499, 52773, 60960, 60974, 60992, 64807, 90, 149, 171, 197, + 208, 238, 282, 341, 353, 357, 518, 553, 681, 744, 770, 1098, 1156, 1280, 1296, 1361, 1472, 1634, 2188, 2328, + 2721, 2864, 3266, 3744, 4357, 4420, 5200, 5441, 6530, 7496, 8729, 8738, 9585, 9801, 9929, 10553, 11395, + 11497, 12576, 14977, 15249, 17417, 21778, 22794, 22859, 22977, 23696, 23818, 23937, 26129, 26251, 29715, + 29746, 30055, 30479, 30480, 30496, 33989, 34870, 34888, 34892, 34905, 34915, 34919, 34989, 35017, 38213, + 39191, 39713, 40741, 45954, 45965, 45990, 46924, 47908, 49347, 50317, 50582, 50735, 50853, 52240, 52267, + 52771, 54423, 56581, 57506, 57510, 57575, 59492, 59971, 59991, 60102, 60936, 60982, 198, 374, 1097, 1225, + 7488, 15113, 17441, 17472, 26387, 29883, 30211, 34879, 35205, 50463, 50999, 52258, 61071 }; + + +static int cbest_17[1023] = { + 1, 2, 65540, 4, 32770, 8, 16385, 16, 32, 73732, 64, 128, 36866, 256, 512, 18433, 1024, 2048, 4096, 74756, + 8192, 16384, 37378, 32768, 3, 18689, 65536, 65541, 5, 32771, 65542, 6, 9, 18, 36, 72, 144, 288, 576, 1152, + 2304, 4608, 9216, 18432, 98310, 10, 17, 16387, 32774, 36864, 65548, 81925, 12, 33, 16389, 32778, 49155, + 65556, 73728, 73733, 74884, 20, 34, 65, 16393, 32786, 65572, 73734, 24, 66, 129, 16401, 32802, 36867, 65604, + 106502, 40, 68, 130, 257, 16417, 32834, 65668, 73740, 90117, 102406, 48, 132, 258, 513, 16449, 32898, 36870, + 37442, 65796, 73748, 80, 136, 260, 514, 1025, 16513, 18435, 33026, 36874, 53251, 66052, 73764, 83973, 96, + 264, 516, 1026, 2049, 16641, 18437, 33282, 36882, 51203, 66564, 73796, 160, 272, 520, 1028, 2050, 4097, + 16897, 18441, 18688, 33794, 36898, 37376, 67588, 73860, 74752, 74757, 110598, 192, 528, 1032, 2052, 4098, + 8193, 9344, 17409, 18449, 18721, 34818, 36930, 69636, 73988, 74758, 320, 544, 1040, 2056, 4100, 4672, 8194, + 18465, 36994, 74244, 92165, 107526, 384, 1056, 2064, 2336, 4104, 8196, 16386, 18497, 20481, 37122, 37379, + 40962, 74764, 81924, 91141, 640, 1088, 1168, 2080, 4112, 8200, 16388, 18561, 24577, 32769, 49154, 55299, + 74772, 75780, 102918, 584, 768, 2112, 4128, 8208, 16392, 37382, 37890, 74788, 77828, 98308, 292, 1280, 2176, + 4160, 8224, 16400, 18945, 32772, 32784, 37386, 38914, 53763, 65537, 74820, 74900, 146, 1536, 4224, 8256, + 16416, 18691, 19457, 32776, 37394, 49153, 65538, 65543, 65568, 84229, 90116, 111622, 7, 19, 37, 73, 145, 289, + 577, 1153, 2305, 2560, 4352, 4609, 8320, 9217, 16448, 18693, 37410, 45058, 51459, 75012, 98306, 98311, + 111110, 11, 38, 74, 290, 578, 1154, 2306, 3072, 4610, 8448, 9218, 16512, 18434, 18697, 22529, 32775, 32800, + 36865, 53250, 65544, 65549, 65558, 65612, 65684, 65828, 66116, 66692, 67844, 70148, 75268, 81921, 83972, + 93189, 106500, 13, 22, 76, 148, 580, 1156, 2308, 4612, 5120, 8704, 9220, 16640, 18436, 18705, 26625, 32779, + 32806, 32832, 32842, 32914, 33058, 33346, 33922, 35074, 37506, 41986, 51202, 65550, 65552, 65557, 73729, + 74880, 74885, 81927, 102404, 14, 21, 26, 35, 44, 152, 296, 1160, 2312, 4616, 6144, 9224, 16391, 16403, 16421, + 16457, 16529, 16673, 16896, 16961, 17537, 18440, 20993, 25601, 32787, 32896, 36868, 36880, 37440, 37450, + 37634, 65573, 73730, 73735, 73760, 74886, 76804, 92421, 98318, 114695, 25, 52, 67, 88, 304, 592, 2320, 4624, + 9232, 10240, 16395, 17408, 18448, 18720, 18753, 32782, 32803, 33024, 36872, 49159, 53249, 55811, 65574, + 65600, 65605, 78852, 81933, 98326, 106498, 106503, 107654, 41, 50, 69, 104, 131, 176, 608, 1184, 4640, 9248, + 12288, 16397, 18464, 18817, 32790, 32835, 33280, 38402, 49163, 51201, 55555, 65564, 65606, 65664, 65669, + 73736, 73741, 73750, 73804, 73876, 74020, 74308, 74892, 76036, 78340, 81941, 90113, 91269, 92164, 98342, + 102402, 102407, 28, 42, 49, 70, 82, 100, 133, 208, 259, 352, 1216, 2368, 9280, 9360, 16405, 16419, 18496, + 20480, 32794, 32899, 33792, 36871, 36896, 37443, 39426, 49171, 65580, 65670, 65792, 65797, 73742, 73744, + 73749, 81957, 90119, 91140, 98374, 110596, 81, 134, 137, 164, 200, 261, 416, 515, 704, 2432, 4736, 16409, + 16451, 18560, 19201, 24576, 32810, 32838, 33027, 34816, 36875, 36902, 36928, 36938, 37010, 37154, 38018, + 39170, 46082, 49187, 55298, 65588, 65798, 66048, 66053, 73765, 74916, 81989, 83969, 98438, 102982, 106510, + 112134, 122887, 97, 138, 262, 265, 274, 328, 400, 517, 832, 1027, 1408, 4680, 4864, 9472, 16425, 16453, + 16515, 18725, 19713, 32818, 32902, 33283, 36883, 36992, 37446, 45570, 49219, 65620, 65676, 66054, 66560, + 66565, 73766, 73792, 73797, 74948, 82053, 83975, 90125, 98566, 102414, 106518, 107524, 118791, 56, 84, 98, + 140, 161, 266, 273, 518, 521, 530, 548, 656, 800, 1029, 1664, 2051, 2816, 9728, 16433, 16517, 16643, 18439, + 18451, 18469, 18505, 18577, 18944, 19009, 19585, 23041, 27649, 32850, 32906, 33030, 33795, 36878, 36899, + 37120, 37377, 40960, 49283, 53255, 53762, 53827, 65636, 65804, 66566, 67584, 67589, 73756, 73798, 73856, + 73861, 74753, 82181, 90133, 98822, 102422, 106534, 110594, 110599, 111750, 116743, 162, 193, 268, 522, 529, + 1030, 1033, 1042, 1060, 1096, 1312, 1600, 2053, 2340, 3328, 4099, 5632, 9345, 16465, 16521, 16645, 16899, + 18443, 18690, 19456, 22785, 32866, 33034, 33286, 34819, 36886, 36931, 37458, 49152, 49411, 51207, 53259, + 55297, 65700, 65812, 66060, 67590, 69632, 69637, 73772, 73862, 73984, 73989, 74754, 74759, 74784, 75140, + 82437, 83981, 84228, 90149, 93445, 99334, 102438, 102916, 106566, 194, 276, 321, 524, 545, 1034, 1041, 2054, + 2057, 2066, 2084, 2120, 2192, 2624, 3200, 4101, 4673, 6656, 8195, 9346, 11264, 16481, 16649, 16901, 17411, + 18445, 18692, 18723, 26881, 32930, 33042, 33290, 33798, 36890, 36995, 37380, 37392, 37474, 37888, 49667, + 51211, 51458, 53267, 65732, 66068, 66572, 69638, 73780, 73990, 74240, 74245, 75396, 82949, 83989, 84261, + 90181, 92161, 93317, 100358, 102470, 106630, 107522, 107527, 111174, 112, 168, 196, 280, 322, 385, 532, 546, + 1036, 1057, 1170, 2058, 2065, 2337, 4102, 4105, 4114, 4132, 4168, 4240, 4384, 4674, 5248, 6400, 8197, 9348, + 13312, 16545, 16657, 16905, 17413, 18453, 18467, 18696, 22528, 32962, 33298, 33802, 34822, 36906, 36934, + 37123, 37384, 38912, 40963, 42114, 50179, 51219, 51491, 53283, 53761, 65860, 66084, 66580, 67596, 70212, + 73812, 73868, 74246, 74760, 74765, 74774, 74828, 75044, 75332, 77060, 79364, 81920, 84005, 90245, 91137, + 92167, 93188, 102534, 106758, 110606, 126983, 324, 386, 536, 641, 1044, 1058, 1089, 1169, 2060, 2081, 2338, + 4106, 4113, 4676, 8198, 8201, 8210, 8228, 8264, 8336, 8480, 8768, 9352, 10496, 12800, 16577, 16913, 17417, + 18457, 18499, 18704, 18729, 20483, 25729, 26624, 33090, 33314, 33810, 34826, 36914, 36998, 37570, 51235, + 53315, 56067, 65924, 66596, 67604, 67876, 69644, 73828, 73996, 74766, 74768, 74773, 75776, 75781, 76932, + 81926, 84037, 86021, 90373, 91143, 102662, 102914, 102919, 107014, 110614, 111620, 124935, 388, 552, 585, + 642, 769, 1048, 1090, 2068, 2082, 2113, 4108, 4129, 8202, 8209, 16390, 16402, 16420, 16456, 16528, 16672, + 16705, 16929, 16960, 17425, 17536, 18473, 18501, 18563, 18737, 20485, 20992, 21057, 24579, 25600, 32912, + 33154, 33826, 34834, 35106, 36946, 37002, 37126, 37383, 37408, 37698, 37891, 40966, 45056, 51267, 51457, + 53379, 65824, 66180, 66628, 66708, 67620, 69652, 73892, 74004, 74252, 74789, 74902, 75782, 77824, 77829, + 78980, 84101, 90629, 92173, 92420, 98304, 98309, 107534, 110630, 111108, 114694, 120839, 123911, 392, 644, + 770, 1281, 2072, 2114, 2177, 4116, 4130, 4161, 8204, 8225, 16769, 17441, 18565, 24581, 33410, 33938, 34850, + 36962, 37130, 38530, 38915, 40970, 46594, 49158, 53248, 55303, 55810, 69668, 73924, 74260, 74790, 74821, + 74896, 74901, 77830, 91149, 92181, 92453, 107542, 110662 }; + +static int cbest_18[1023] = { + 1, 2, 131136, 4, 65568, 8, 32784, 16, 16392, 32, 8196, 64, 4098, 128, 2049, 256, 512, 132160, 1024, 2048, + 66080, 4096, 33040, 8192, 16520, 8260, 16384, 3, 4130, 32768, 131137, 5, 65569, 131138, 6, 9, 2065, 32785, + 65536, 65570, 131140, 196704, 10, 17, 16393, 32786, 65572, 131144, 163920, 12, 18, 33, 8197, 16394, 32788, + 65576, 98352, 131072, 131152, 147528, 20, 34, 65, 4099, 8198, 16396, 32792, 65584, 81960, 131168, 132168, + 139332, 24, 36, 66, 129, 258, 516, 1032, 2064, 49176, 73764, 135234, 40, 68, 130, 257, 2051, 4102, 4128, + 8204, 16408, 32816, 40980, 65632, 69666, 131264, 133185, 48, 72, 132, 513, 2053, 4106, 8212, 8256, 16424, + 24588, 32848, 36882, 65696, 66084, 67617, 131392, 132161, 80, 136, 260, 514, 1025, 2057, 4114, 8228, 16456, + 16512, 20490, 32912, 34833, 65824, 131648, 132162, 96, 144, 264, 1026, 12294, 18441, 33024, 66081, 132164, + 197728, 160, 272, 520, 1028, 2050, 2081, 4162, 8324, 10245, 16648, 33042, 33296, 66048, 66082, 66592, 133184, + 164944, 197216, 192, 288, 528, 2052, 2113, 4097, 4226, 6147, 8452, 16904, 33041, 33808, 67616, 132096, + 132176, 148552, 320, 544, 1040, 2056, 2177, 4354, 8708, 17416, 34832, 66088, 98864, 132192, 135232, 140356, + 164176, 384, 576, 1056, 2305, 4100, 4610, 8193, 9220, 16521, 18440, 33044, 66096, 69664, 82472, 98608, + 136258, 640, 1088, 2080, 2561, 4104, 5122, 8194, 10244, 16522, 33048, 36880, 74276, 132288, 134209, 139268, + 139328, 147656, 768, 1152, 2112, 3073, 4112, 6146, 8261, 16385, 16524, 20488, 49432, 66144, 69634, 70178, + 73760, 82088, 132416, 1280, 2176, 8200, 8262, 12292, 16386, 33072, 34817, 40976, 41236, 49304, 66208, 68129, + 132672, 147520, 1536, 2304, 4131, 4160, 4352, 8208, 16388, 16536, 24584, 32769, 33104, 37138, 66336, 73828, + 81952, 2560, 4224, 6145, 8224, 8268, 8704, 16552, 24716, 32770, 33168, 35089, 41044, 49168, 131139, 134208, + 135266, 148544, 163904, 198240, 7, 3072, 4134, 8276, 12290, 16400, 16584, 17408, 20618, 24652, 32772, 65537, + 65571, 67104, 98336, 131141, 196705, 11, 2067, 4138, 4608, 8292, 8320, 10241, 16416, 18569, 24580, 32776, + 32787, 33552, 34816, 36914, 65538, 65573, 68128, 74272, 131142, 131145, 133201, 136256, 163921, 165200, + 196672, 196706, 13, 19, 2069, 4146, 5120, 8448, 12358, 16395, 16448, 16776, 20482, 20522, 32789, 34064, + 49160, 65540, 65574, 65577, 67633, 98353, 131073, 131146, 131153, 147529, 163922, 196708, 14, 21, 35, 2073, + 6144, 8199, 8388, 10309, 12326, 16397, 17032, 18433, 32790, 32793, 32800, 35088, 37136, 40964, 65544, 65578, + 65585, 69632, 70176, 81961, 98320, 98354, 99120, 131074, 131148, 131154, 131169, 132169, 139333, 140292, + 140352, 147530, 148680, 163924, 196712, 229488, 22, 25, 37, 67, 259, 517, 1033, 4194, 8516, 9216, 16398, + 16640, 17544, 18457, 32794, 32832, 36866, 49177, 65552, 65580, 65586, 73765, 81928, 81962, 98356, 131076, + 131156, 131170, 132170, 135235, 139334, 147532, 163928, 196640, 196720, 213096, 26, 38, 41, 69, 131, 518, + 1034, 2066, 2097, 4103, 4129, 4258, 6179, 8205, 8772, 10240, 10261, 16409, 16896, 18568, 32796, 32817, 32896, + 40981, 49178, 65588, 65633, 69667, 70146, 73732, 73766, 81964, 82600, 98360, 131080, 131160, 131172, 131265, + 131394, 131652, 132172, 133200, 139264, 163856, 180312, 197736, 204900, 28, 42, 49, 70, 73, 133, 262, 1036, + 2068, 2129, 4107, 4386, 6163, 8206, 8213, 8257, 9284, 16410, 16425, 24589, 32818, 32849, 36883, 40982, 49180, + 65592, 65600, 65634, 65697, 65826, 66085, 66600, 67632, 114744, 131088, 131176, 131266, 131393, 133187, + 135238, 135264, 139340, 147464, 147544, 163952, 164952, 172116, 200802, 44, 50, 74, 81, 134, 137, 261, 266, + 515, 524, 2055, 2072, 2193, 4115, 4132, 4642, 8214, 8229, 8258, 10308, 12288, 16412, 16426, 16457, 16513, + 18432, 20491, 20616, 24590, 32820, 32850, 32913, 33026, 33280, 33300, 33816, 35073, 41232, 49560, 65636, + 65664, 65698, 65825, 66052, 66086, 67585, 67619, 69670, 73772, 74340, 81976, 82464, 106548, 131104, 131184, + 131268, 131649, 132104, 132163, 132184, 133189, 135242, 136290, 139348, 147560, 155724, 164928, 168018, + 196832, 197220, 198753, 52, 76, 82, 97, 138, 145, 265, 274, 532, 1027, 1048, 2059, 2321, 4110, 4136, 5154, + 8230, 12295, 16428, 16458, 16514, 16650, 16908, 18456, 32824, 32852, 32914, 33025, 33792, 34835, 36886, + 36912, 40988, 65640, 65700, 65792, 67621, 69674, 73780, 73824, 90156, 98416, 102450, 131272, 131396, 131650, + 132165, 132200, 133193, 135170, 135250, 139364, 140364, 147648, 151626, 164048, 165969, 196960, 197729, 56, + 84, 98, 140, 146, 161, 273, 290, 521, 548, 1029, 1064, 2061, 2096, 2577, 4118, 4144, 4163, 6178, 8220, 8264, + 8325, 8454, 9228, 10260, 12356, 16460, 16516, 16649, 18443, 20480, 20494, 20520, 24712, 32856, 32916, 33043, + 33297, 34837, 36890, 41040, 41300, 49208, 49424, 57372, 65648, 65704, 65828, 66049, 66083, 66092, 66593, + 67625, 69682, 82024, 82080, 86058, 98480, 98848, 98868, 100401, 131200, 131280, 131400, 132166, 133121, + 134225, 136266, 143430, 149577, 164160, 164945, 197217, 197696, 197730, 88, 100, 148, 162, 193, 268, 289, + 322, 522, 529, 580, 1030, 1096, 2083, 2128, 3089, 4122, 4227, 4614, 5130, 6162, 8236, 8272, 8326, 8453, + 10247, 12324, 16440, 16905, 18445, 24604, 24648, 32920, 33028, 33298, 33809, 34841, 41012, 49240, 49296, + 53274, 65712, 65832, 66050, 66100, 66560, 66594, 77862, 82476, 84009, 98592, 131296, 131328, 131408, 131656, + 132097, 132177, 132296, 133186, 133217, 134217, 139460, 141381, 147784, 148553, 148672, 164178, 164432, + 164946, 197184, 197218, 197732, 104, 152, 164, 194, 276, 321, 386, 530, 545, 644, 1041, 1160, 2054, 2085, + 2115, 2192, 2307, 2565, 3081, 4166, 4192, 4355, 4384, 8244, 8288, 8709, 8768, 12302, 16472, 16528, 16652, + 16906, 17417, 17536, 20506, 24576, 24620, 24780, 32880, 33032, 33046, 33810, 35072, 36864, 37170, 45078, + 51225, 65840, 66089, 66596, 67584, 67618, 68145, 69730, 73892, 75813, 82216, 98610, 98865, 131424, 131584, + 131664, 132098, 132178, 132193, 132424, 133188, 135233, 135362, 137283, 139588, 140357, 148040, 148554, + 164177, 164948, 198752, 230512, 112, 168, 196, 280, 292, 385, 546, 577, 772, 1042, 1057, 1288, 2058, 2089, + 2117, 2179, 2320, 4101, 4170, 4230, 4256, 4611, 6151, 6177, 8332, 8710, 9221, 10253, 12310, 12354, 16488, + 16544, 17418, 24708, 28686, 32944, 33045, 33050, 33304, 33812, 34834, 34865, 36946, 41108, 43029, 49416, + 65760, 66056, 66090, 66097, 66148, 67620, 67681, 69665, 69794, 70144, 70182, 71715, 74020, 82473, 98609, + 98832, 98866, 99376, 131680, 132100, 132180, 132194, 132680, 133192, 133313, 135490, 136259, 139844, 140358, + 148556, 165968, 197224, 197664, 197744, 214120, 230000, 176, 200, 296, 324, 536, 641, 770, 1044, 1058, 1089, + 1544, 2060, 2121, 2181, 4105, 4178, 4234, 4358, 8460, 9222, 10305, 16576, 17420, 18442, 18473, 20554, 20610, + 32976, 33049, 33056, 34836, 34897, 38931, 41220, 65888, 66098, 66608, 67624, 67745, 68133, 74277, 74336, + 82440, 82474, 131520, 132196, 132418, 133120, 133441, 134224, 135746, 164880, 181336, 197232, 205924, 229744 }; + + +static int cbest_19[1023] = { + 1, 2, 262163, 4, 393242, 8, 196621, 16, 32, 360469, 64, 262162, 128, 131081, 3, 442393, 262161, 6, 256, + 393243, 5, 327703, 12, 196620, 512, 393240, 9, 24, 98310, 262167, 426008, 10, 458782, 48, 1024, 49155, + 196617, 17, 213004, 262171, 393234, 483359, 18, 96, 262147, 360471, 393246, 20, 2048, 16385, 196623, 286738, + 360468, 442392, 33, 192, 32770, 106502, 229391, 34, 65540, 196613, 270355, 360465, 36, 384, 4096, 131080, + 143369, 180234, 393226, 40, 65, 53251, 221196, 262195, 66, 768, 376852, 397338, 442395, 68, 8192, 24577, + 49154, 90117, 503836, 72, 129, 1536, 262160, 262227, 80, 110598, 198669, 288786, 393274, 132, 3072, 16384, + 98308, 188426, 196637, 274451, 327702, 333847, 483358, 7, 130, 136, 257, 131083, 262291, 307217, 144, 6144, + 49153, 163851, 213005, 262165, 286739, 327699, 360477, 393241, 393306, 426010, 13, 160, 55299, 131073, + 144393, 196616, 196653, 262166, 327701, 360453, 361493, 426009, 14, 26, 258, 264, 513, 12288, 53250, 94213, + 131085, 196609, 262419, 399386, 442385, 458783, 25, 52, 272, 26625, 98306, 98311, 251918, 344086, 360467, + 393370, 429080, 442397, 11, 104, 288, 24576, 32768, 90116, 106500, 196619, 196622, 196685, 229389, 262155, + 262170, 262175, 311312, 368661, 393218, 393235, 393238, 393244, 405530, 458778, 22, 28, 49, 208, 260, 320, + 514, 1025, 45058, 155656, 180235, 229390, 241679, 262146, 262169, 262675, 360470, 376853, 393232, 393247, + 442394, 458780, 44, 416, 528, 22529, 77828, 172043, 180232, 196612, 199693, 213000, 221197, 262145, 262179, + 289810, 360501, 393498, 415771, 442905, 483355, 491548, 19, 88, 97, 544, 832, 38914, 53249, 143368, 196749, + 275475, 309265, 442377, 475167, 483357, 21, 38, 50, 56, 176, 516, 576, 1026, 1664, 2049, 19457, 71684, + 114695, 131097, 135177, 202765, 214540, 263187, 270354, 288787, 334359, 360464, 426000, 76, 193, 352, 640, + 3328, 32771, 35842, 49152, 106498, 106503, 139273, 213006, 229387, 262151, 278546, 286736, 327711, 352278, + 360533, 393227, 393754, 426012, 446489, 458774, 35, 98, 152, 194, 704, 1056, 6656, 17921, 55298, 65536, + 65541, 196629, 196877, 245774, 262194, 262259, 273427, 294929, 319504, 327687, 348182, 376854, 393224, + 393258, 450585, 37, 42, 70, 112, 304, 385, 520, 1028, 1088, 1408, 2050, 4097, 13312, 16387, 49159, 94212, + 110596, 125959, 131113, 144905, 188427, 196615, 212996, 262193, 264211, 270353, 315408, 329751, 360473, + 362005, 372757, 382996, 397339, 483351, 503838, 41, 140, 608, 1152, 2816, 26624, 27649, 98318, 159752, + 188424, 198668, 221192, 262355, 271891, 331799, 360597, 394266, 399898, 442425, 499740, 503837, 67, 100, 280, + 388, 769, 1216, 1280, 5632, 47106, 65542, 98304, 99334, 107270, 157704, 176139, 196633, 196636, 197133, + 262226, 363541, 376848, 393230, 406554, 409627, 425992, 427032, 442384, 69, 74, 84, 224, 386, 560, 1032, + 2052, 2112, 2432, 4098, 8193, 11264, 16389, 49163, 49667, 79876, 90113, 122887, 131082, 131145, 143371, + 163849, 174091, 229383, 262199, 262225, 262547, 266259, 271123, 286742, 344087, 360479, 393275, 393338, + 397336, 428056, 429336, 442396, 458766, 470046, 483615, 503832, 73, 196, 1120, 1537, 2176, 4864, 22528, + 23553, 32774, 55297, 78852, 81925, 98326, 163850, 213516, 221198, 262203, 274450, 307219, 311313, 327735, + 333846, 360455, 360725, 393266, 393272, 395290, 398874, 416795, 442399, 442457, 460830, 81, 134, 770, 776, + 2240, 2304, 9728, 39938, 53248, 110594, 110599, 131072, 137225, 143361, 144392, 180226, 196649, 196652, + 196669, 197645, 198665, 214028, 251919, 262290, 262931, 270359, 286994, 303121, 307216, 327697, 356374, + 360449, 393434, 434200, 442387, 483343, 133, 148, 168, 448, 1040, 2056, 2560, 3073, 4100, 4480, 8194, 16393, + 16897, 19456, 24579, 39426, 49171, 90119, 98309, 106758, 114694, 131084, 131209, 143373, 180238, 191498, + 196608, 199949, 221188, 249870, 251916, 262164, 262211, 262231, 275987, 286746, 288784, 289811, 323600, + 327698, 333843, 360461, 360476, 361495, 393307, 398106, 415770, 426011, 442904, 443161, 448537, 466974, + 483354, 485407, 131, 137, 200, 1538, 4224, 8960, 17409, 19969, 32778, 53255, 53635, 57347, 72196, 98342, + 106510, 107014, 131077, 143497, 153608, 155657, 196639, 196717, 203277, 213020, 217100, 262235, 263699, + 270611, 274449, 286722, 325136, 327700, 327767, 333845, 350230, 360452, 360981, 361492, 393278, 393298, + 393304, 393626, 397330, 426040, 442376, 442521, 475166, 483356, 487455, 82, 138, 145, 268, 772, 1552, 4352, + 6145, 17920, 18433, 19713, 33794, 45056, 53379, 65548, 106496, 166923, 180233, 196618, 196645, 196681, + 196684, 198671, 213001, 229385, 229388, 230415, 241677, 262289, 262418, 270363, 270867, 317456, 334615, + 349206, 360485, 397342, 397722, 399387, 417819, 429082, 442369, 442389, 443929, 458814, 503828, 146, 161, + 296, 336, 392, 896, 2064, 3074, 4104, 4608, 8196, 16386, 16401, 20481, 24581, 34818, 36098, 49158, 49187, + 53507, 76804, 108550, 125958, 131087, 131089, 131337, 161800, 172041, 180746, 196813, 199437, 214668, 221452, + 241678, 262153, 262275, 262295, 265235, 270339, 271379, 273939, 278547, 286737, 290834, 311314, 327707, + 330775, 352279, 360466, 360503, 361489, 368663, 393216, 393371, 394010, 397466, 413723, 429081, 446488, + 458770, 458776, 15, 27, 54, 108, 162, 216, 259, 265, 432, 864, 1540, 1728, 3456, 5120, 6912, 12289, 13824, + 27648, 32786, 36866, 38912, 49157, 53259, 67588, 94209, 98374, 106518, 131075, 172042, 178187, 196655, + 198661, 199692, 213036, 214541, 229407, 233487, 262154, 262174, 262299, 272403, 319505, 327831, 348183, + 360497, 368660, 376855, 393219, 393239, 393245, 393290, 393310, 393362, 397594, 401434, 405531, 426014, + 426072, 442379, 442649, 450584, 458779, 483391, 503964, 514077, 53, 266, 273, 536, 3104, 6146, 8448, 18049, + 24833, 38402, 40962, 54275, 65556, 69636, 86021, 90373, 98307, 114693, 124935, 145417, 158728, 188418, + 196611, 196677, 196745, 196748, 197005, 198733, 199053, 200717, 207885, 212992, 213007, 235023, 237583, + 251914, 262168, 262173, 262417, 262674, 268307, 288790, 288850, 315409, 339991, 344082, 376860, 377364, + 382997, 393233, 393236, 394778, 397850, 399384, 426002, 442907, 458781, 458846, 483347, 483350, 483353, + 491550, 30, 105, 262, 274, 289, 400, 592, 672, 1792, 2080, 3076, 4112, 8200, 8704, 16388, 16417, 24585, + 32769, 35840, 49162, 49219, 49666, 73732, 80900, 90112, 90125, 95749, 98314, 99846, 106501, 110726, 122886, + 131096, 131593, 135176, 143385, 144395, 175115, 180250, 184330, 188430, 198797, 202764, 223244, 245775, + 262144, 262149, 262178, 262183, 262323, 262403, 272147, 274455, 286770, 288914, 309267, 333911, 344084, + 360500, 360535, 360565, 362133, 368657, 376836, 388116, 393368, 393499, 397322, 398362, 400154, 407066, + 427544, 438296, 442424, 491549, 23, 29, 46, 92, 106, 184, 209, 261, 276, 290, 321, 368, 515, 736, 1472, 1544, + 2944, 5888, 9216, 11776, 12290, 19201, 23552, 32802, 45059, 53267, 55296, 81924, 94215, 98316, 98438, 106534, + 139272, 163843, 174603, 196687, 197389, 198861, 198925, 212997, 213002, 213068, 221212, 225292, 229386, + 229423, 241675, 245772, 262427, 272019, 274579, 275474, 288978, 305169, 307221, 309264, 327959, 345622, + 360529, 362517, 363797, 376849, 378900, 393354, 393374, 393490, 396314, 405528, 409626, 426136, 436248, + 461854, 470558, 471070, 483423, 503820, 504860, 417, 529, 1072, 6148, 10240, 92165, 101382, 125957, 144425, + 147464, 196741, 204813, 262159, 262339, 262673, 263186, 286743, 288794, 307345, 327683, 425984, 426001, + 432152, 442409, 458910, 505884 }; + +static int cbest_20[1023] = { + 1, 2, 524292, 4, 262146, 8, 131073, 16, 32, 589828, 64, 128, 294914, 256, 512, 147457, 1024, 2048, 4096, + 598020, 8192, 16384, 32768, 299010, 65536, 131072, 149505, 262144, 3, 524288, 524293, 5, 262147, 524294, + 599044, 6, 9, 18, 36, 72, 144, 288, 576, 1152, 2304, 4608, 9216, 18432, 36864, 73728, 147456, 786438, 10, 17, + 131075, 262150, 294912, 524300, 655365, 12, 33, 131077, 262154, 393219, 524308, 589824, 589829, 20, 34, 65, + 131081, 262162, 299522, 524324, 589830, 24, 66, 129, 131089, 262178, 294915, 524356, 851974, 40, 68, 130, + 257, 131105, 262210, 524420, 589836, 720901, 819206, 48, 132, 258, 513, 131137, 262274, 294918, 524548, + 589844, 80, 136, 260, 514, 1025, 131201, 147459, 149761, 262402, 294922, 425987, 524804, 589860, 671749, 96, + 264, 516, 1026, 2049, 131329, 147461, 262658, 294930, 409603, 525316, 589892, 160, 272, 520, 1028, 2050, + 4097, 131585, 147465, 149504, 263170, 294946, 299008, 526340, 589956, 598016, 598021, 884742, 192, 528, 1032, + 2052, 4098, 8193, 74752, 132097, 147473, 264194, 294978, 528388, 590084, 598022, 320, 544, 1040, 2056, 4100, + 8194, 16385, 37376, 133121, 147489, 266242, 295042, 532484, 590340, 737285, 860166, 384, 1056, 2064, 4104, + 8196, 16386, 18688, 32769, 135169, 147521, 270338, 295170, 299011, 540676, 590852, 598028, 599172, 729093, + 640, 1088, 2080, 4112, 8200, 9344, 16388, 32770, 65537, 139265, 147585, 278530, 295426, 442371, 557060, + 591876, 598036, 823302, 768, 2112, 4128, 4672, 8208, 16392, 32772, 65538, 147713, 295938, 299014, 593924, + 598052, 1280, 2176, 2336, 4160, 8224, 16400, 32776, 65540, 131074, 147969, 163841, 296962, 299018, 327682, + 430083, 598084, 655364, 1168, 1536, 4224, 8256, 16416, 32784, 65544, 131076, 148481, 149507, 196609, 262145, + 299026, 393218, 598148, 606212, 673797, 892934, 584, 2560, 4352, 8320, 16448, 32800, 65552, 131080, 149509, + 299042, 299586, 303106, 411651, 598276, 622596, 786436, 888838, 292, 3072, 8448, 16512, 32832, 65568, 131088, + 149513, 151553, 262148, 262160, 299074, 311298, 524289, 598532, 745477, 146, 5120, 8704, 16640, 32896, 65600, + 131104, 149521, 155649, 262152, 299138, 393217, 524290, 524295, 524320, 599040, 599045, 720900, 7, 19, 37, + 73, 145, 289, 577, 1153, 2305, 4609, 6144, 9217, 16896, 18433, 33024, 36865, 65664, 73729, 131136, 149537, + 299266, 299520, 360450, 599046, 600068, 739333, 786434, 786439, 11, 38, 74, 290, 578, 1154, 2306, 4610, 9218, + 10240, 17408, 18434, 33280, 36866, 65792, 73730, 131200, 147458, 149569, 149760, 180225, 262151, 262176, + 294913, 425986, 446467, 524296, 524301, 524310, 524364, 524436, 524580, 524868, 525444, 526596, 528900, + 533508, 542724, 561156, 602116, 655361, 671748, 851972, 861190, 13, 22, 76, 148, 580, 1156, 2308, 4612, 9220, + 12288, 18436, 33792, 36868, 66048, 73732, 131328, 147460, 149633, 149793, 212993, 262155, 262182, 262208, + 262218, 262290, 262434, 262722, 263298, 264450, 266754, 271362, 280578, 300034, 335874, 409602, 444419, + 524302, 524304, 524309, 589825, 599052, 655367, 730117, 819204, 14, 21, 26, 35, 44, 152, 296, 1160, 2312, + 4616, 9224, 18440, 20480, 34816, 36872, 66560, 73736, 74880, 131079, 131091, 131109, 131145, 131217, 131361, + 131584, 131649, 132225, 133377, 135681, 140289, 147464, 167937, 204801, 262163, 262272, 294916, 294928, + 299523, 301058, 524325, 589826, 589831, 589856, 599060, 614404, 786446, 917511, 25, 52, 67, 88, 304, 592, + 2320, 4624, 9232, 18448, 24576, 36880, 67584, 73744, 131083, 132096, 147472, 150017, 262158, 262179, 262400, + 294920, 393223, 425985, 524326, 524352, 524357, 599076, 630788, 655373, 786454, 823814, 851970, 851975, + 897030, 41, 50, 69, 104, 131, 176, 608, 1184, 4640, 9248, 18464, 36896, 37440, 40960, 69632, 73760, 131085, + 133120, 147488, 150529, 262166, 262211, 262656, 299526, 307202, 393227, 409601, 524316, 524358, 524416, + 524421, 589832, 589837, 589846, 589900, 589972, 590116, 590404, 590980, 592132, 594436, 599108, 608260, + 626692, 655381, 720897, 737284, 786470, 819202, 819207, 28, 42, 49, 70, 82, 100, 133, 208, 259, 352, 1216, + 2368, 9280, 18496, 36928, 49152, 73792, 131093, 131107, 135168, 147520, 262170, 262275, 263168, 294919, + 294944, 299530, 315394, 393235, 430595, 524332, 524422, 524544, 524549, 589838, 589840, 589845, 655397, + 720903, 729092, 786502, 884740, 893958, 81, 134, 137, 164, 200, 261, 416, 515, 704, 2432, 4736, 18560, 18720, + 36992, 73856, 81920, 131097, 131139, 139264, 147584, 153601, 262186, 262214, 262403, 264192, 294923, 294950, + 294976, 294986, 295058, 295202, 295490, 296066, 297218, 299538, 304130, 313346, 368642, 393251, 442370, + 524340, 524550, 524800, 524805, 589861, 599300, 655429, 671745, 747525, 786566, 851982, 983047, 97, 138, 262, + 265, 274, 328, 400, 517, 832, 1027, 1408, 4864, 9472, 37120, 73984, 98304, 131113, 131141, 131203, 147712, + 149763, 157697, 262194, 262278, 262659, 266240, 294931, 295040, 299554, 364546, 393283, 524372, 524428, + 524806, 525312, 525317, 589862, 589888, 589893, 599188, 599556, 655493, 671751, 674053, 720909, 746501, + 786694, 819214, 851990, 860164, 889350, 950279, 56, 84, 98, 140, 161, 266, 273, 518, 521, 530, 548, 656, 800, + 1029, 1664, 2051, 2816, 9360, 9728, 18944, 74240, 131121, 131205, 131331, 147463, 147475, 147493, 147529, + 147601, 147745, 147968, 148033, 148609, 149765, 152065, 156673, 163840, 184321, 221185, 262226, 262282, + 262406, 263171, 270336, 294926, 294947, 295168, 299009, 393347, 411907, 425991, 430082, 524388, 524556, + 525318, 526336, 526341, 589852, 589894, 589952, 589957, 598017, 655621, 720917, 786950, 819222, 852006, + 884738, 884743, 933895, 162, 193, 268, 522, 529, 1030, 1033, 1042, 1060, 1096, 1312, 1600, 2053, 3328, 4099, + 5632, 19456, 37888, 74753, 131153, 131209, 131333, 131587, 147467, 148480, 149506, 149769, 182273, 196608, + 262242, 262410, 262662, 264195, 278528, 294934, 294979, 295424, 299650, 393475, 409607, 425995, 442369, + 448515, 524452, 524564, 524812, 526342, 528384, 528389, 589868, 589958, 590080, 590085, 598018, 598023, + 598048, 601092, 655877, 671757, 673796, 720933, 787462, 819238, 823300, 852038, 194, 276, 321, 524, 545, + 1034, 1041, 2054, 2057, 2066, 2084, 2120, 2192, 2624, 3200, 4101, 4680, 6656, 8195, 11264, 37377, 38912, + 74754, 75776, 131169, 131337, 131589, 132099, 147469, 149508, 149777, 215041, 262306, 262418, 262666, 263174, + 266243, 294938, 295043, 295936, 299012, 299024, 299778, 393731, 409611, 411650, 426003, 524484, 524820, + 525324, 528390, 532480, 532485, 589876, 590086, 590336, 590341, 603140, 656389, 671765, 720965, 737281, + 788486, 819270, 852102, 860162, 860167, 112, 168, 196, 280, 322, 385, 532, 546, 1036, 1057, 2058, 2065, 4102, + 4105, 4114, 4132, 4168, 4240, 4384, 5248, 6400, 8197, 13312, 16387, 18689, 22528, 37378, 74756, 77824, + 131233, 131345, 131593, 132101, 133123, 147477, 147491, 149512, 151552, 262338, 262674, 263178, 264198, + 270339, 294954, 294982, 295171, 296960, 299016, 327680, 336898, 394243, 409619, 426019, 430081, 446979, + 524612, 524836, 525332, 526348, 532486, 540672, 540677, 561668, 589908, 589964, 590342, 590848, 590853, + 598024, 598029, 598038, 598092, 598164, 598308, 598596, 599168, 599173, 600324, 602628, 616452, 634884, + 657413, 671781, 721029, 729089, 737287, 739589, 745476, 790534, 819334, 852230, 884750, 1015815, 386, 1089, + 4106, 8228, 8264, 8336, 10496, 131601, 147481, 147523, 149825, 155648, 262466, 263186, 295046, 300546, + 393216, 426051, 590092, 599174, 615428, 729095, 823303 }; + +static int cbest_21[1023] = { + 1, 2, 1048578, 4, 524289, 8, 16, 1310722, 32, 64, 655361, 128, 256, 512, 1376258, 1024, 2048, 4096, 688129, + 8192, 16384, 32768, 65536, 1392642, 131072, 262144, 524288, 696321, 1048576, 3, 1048579, 5, 10, 20, 40, 80, + 160, 320, 640, 1280, 2560, 5120, 10240, 20480, 40960, 81920, 163840, 327680, 655360, 6, 9, 524291, 1048582, + 1310720, 1572867, 17, 524293, 1048586, 1310723, 1396738, 12, 18, 33, 524297, 1048594, 34, 65, 524305, + 1048610, 1310726, 1835011, 24, 36, 66, 129, 524321, 655363, 1048642, 1310730, 1703939, 68, 130, 257, 524353, + 655365, 688128, 1048706, 1310738, 1376256, 48, 72, 132, 258, 513, 344064, 524417, 655369, 698369, 1048834, + 1310754, 1376259, 136, 260, 514, 1025, 172032, 524545, 655377, 1049090, 1310786, 1966083, 96, 144, 264, 516, + 1026, 2049, 86016, 524801, 655393, 1049602, 1310850, 1376262, 1900547, 272, 520, 1028, 2050, 4097, 43008, + 525313, 655425, 1050626, 1310978, 1376266, 192, 288, 528, 1032, 2052, 4098, 8193, 21504, 526337, 655489, + 688131, 1052674, 1311234, 1376274, 1736707, 544, 1040, 2056, 4100, 8194, 10752, 16385, 528385, 655617, + 688133, 1056770, 1311746, 1376290, 384, 576, 1056, 2064, 4104, 5376, 8196, 16386, 32769, 532481, 655873, + 688137, 1064962, 1312770, 1376322, 1392640, 1397762, 2031619, 1088, 2080, 2688, 4112, 8200, 16388, 32770, + 65537, 540673, 656385, 688145, 696320, 1081346, 1314818, 1376386, 1392643, 1998851, 768, 1152, 1344, 2112, + 4128, 8208, 16392, 32772, 65538, 131073, 557057, 657409, 688161, 1114114, 1318914, 1376514, 672, 2176, 4160, + 8224, 16400, 32776, 65540, 131074, 262145, 348160, 589825, 659457, 688193, 1179650, 1327106, 1376770, + 1392646, 1916931, 336, 1536, 2304, 4224, 8256, 16416, 32784, 65544, 131076, 262146, 663553, 688257, 1343490, + 1377282, 1392650, 168, 4352, 8320, 16448, 32800, 65552, 131080, 174080, 262148, 524290, 671745, 688385, + 786433, 1378306, 1392658, 1572866, 84, 3072, 4608, 8448, 16512, 32832, 65568, 131088, 262152, 524292, 688641, + 696323, 698881, 1048577, 1380354, 1392674, 1441794, 1744899, 2064387, 42, 8704, 16640, 32896, 65600, 87040, + 131104, 262160, 524296, 689153, 696325, 720897, 1048584, 1384450, 1392706, 2048003, 11, 21, 41, 81, 161, 321, + 641, 1281, 2561, 5121, 6144, 9216, 10241, 16896, 20481, 33024, 40961, 65664, 81921, 131136, 163841, 262176, + 327681, 524304, 690177, 696329, 1048580, 1392770, 1572865, 1835010, 7, 22, 82, 162, 322, 642, 1282, 2562, + 5122, 10242, 17408, 20482, 33280, 40962, 43520, 65792, 81922, 131200, 163842, 262208, 327682, 524320, 655362, + 692225, 696337, 917505, 1048583, 1048598, 1048618, 1048658, 1048738, 1048898, 1049218, 1049858, 1051138, + 1053698, 1058818, 1069058, 1089538, 1130498, 1212418, 1310721, 1392898, 1396736, 1409026, 1703938, 2007043, + 14, 44, 164, 324, 644, 1284, 2564, 5124, 10244, 12288, 18432, 20484, 33792, 40964, 66048, 81924, 131328, + 163844, 262272, 327684, 524299, 524309, 524329, 524352, 524369, 524449, 524609, 524929, 525569, 526849, + 529409, 534529, 544769, 565249, 606209, 655364, 696353, 851969, 1048587, 1048592, 1310728, 1393154, 1396739, + 13, 19, 28, 88, 328, 648, 1288, 2568, 5128, 10248, 20488, 21760, 34816, 40968, 66560, 81928, 131584, 163848, + 262400, 327688, 524295, 524416, 655368, 696385, 698368, 704513, 1048595, 1048608, 1310724, 1393666, 1507330, + 1572871, 1835009, 26, 35, 56, 176, 656, 1296, 2576, 5136, 10256, 20496, 24576, 36864, 40976, 67584, 81936, + 132096, 163856, 262656, 327696, 524544, 655376, 696449, 1048590, 1048611, 1048640, 1310727, 1310742, 1310762, + 1310802, 1310882, 1311042, 1311362, 1312002, 1313282, 1315842, 1320962, 1331202, 1351682, 1394690, 1396742, + 1474562, 1572875, 1703937, 1921027, 1966082, 25, 37, 52, 67, 112, 352, 1312, 2592, 5152, 10272, 10880, 20512, + 40992, 69632, 81952, 133120, 163872, 263168, 327712, 524301, 524307, 524800, 655392, 696577, 753665, 1048643, + 1048704, 1310731, 1310736, 1396746, 1398018, 1572883, 1900546, 2080771, 38, 69, 74, 104, 131, 224, 704, 2624, + 5184, 10304, 20544, 41024, 49152, 73728, 81984, 135168, 163904, 264192, 327744, 349184, 524323, 525312, + 655371, 655381, 655401, 655424, 655441, 655521, 655681, 656001, 656641, 657921, 660481, 665601, 675841, + 696833, 737281, 983041, 1048602, 1048614, 1048707, 1048832, 1310739, 1310752, 1376257, 1396754, 1400834, + 1572899, 1835015, 2072579, 49, 70, 73, 133, 138, 148, 208, 259, 448, 1408, 5248, 5440, 10368, 20608, 41088, + 82048, 139264, 163968, 266240, 327808, 344065, 524313, 524325, 524355, 526336, 655367, 655488, 688130, + 697345, 950273, 1048646, 1048835, 1049088, 1310734, 1310755, 1310784, 1376264, 1396770, 1572931, 1703943, + 1736706, 1835019, 1966081, 50, 134, 137, 261, 266, 276, 296, 416, 515, 896, 2816, 10496, 20736, 41216, 82176, + 98304, 147456, 164096, 172033, 270336, 327936, 344066, 524357, 524419, 528384, 655616, 688132, 698371, + 1048626, 1048650, 1048710, 1049091, 1049600, 1310787, 1310848, 1376260, 1396802, 1425410, 1572995, 1703947, + 1746947, 1835027, 1900545, 2052099, 76, 97, 145, 262, 265, 517, 522, 532, 552, 592, 832, 1027, 1792, 2720, + 5632, 20992, 41472, 82432, 86017, 164352, 172034, 174592, 278528, 328192, 344068, 524337, 524361, 524421, + 524547, 532480, 655373, 655379, 655872, 688136, 698373, 700417, 868353, 1048714, 1048838, 1049603, 1050624, + 1220610, 1310746, 1310758, 1310851, 1310976, 1376263, 1376278, 1376298, 1376338, 1376418, 1376578, 1376898, + 1377538, 1378818, 1381378, 1386498, 1396866, 1417218, 1540098, 1573123, 1703955, 1835043, 2031618, 98, 140, + 146, 273, 518, 521, 1029, 1034, 1044, 1064, 1104, 1184, 1664, 2051, 3584, 11264, 41984, 43009, 82944, 86018, + 164864, 172036, 196608, 294912, 328704, 344072, 524425, 524549, 524803, 540672, 655395, 656384, 688144, + 698377, 1048674, 1048722, 1048842, 1049094, 1050627, 1052672, 1134594, 1310790, 1310979, 1311232, 1376267, + 1376272, 1396994, 1523714, 1573379, 1703971, 1736705, 1835075, 1966087, 1998850, 100, 193, 268, 274, 289, + 529, 1030, 1033, 1360, 2053, 2058, 2068, 2088, 2128, 2208, 2368, 3328, 4099, 7168, 21505, 22528, 43010, + 83968, 86020, 165888, 172040, 329728, 344080, 524385, 524433, 524553, 524805, 525315, 557056, 610305, 655385, + 655397, 655427, 657408, 688160, 698385, 712705, 1048850, 1049098, 1049606, 1052675, 1056768, 1091586, + 1310770, 1310794, 1310854, 1311235, 1311744, 1376275, 1376288, 1397250, 1573891, 1704003, 1835139, 1900551, + 1966091, 2009091, 152, 194, 290, 524, 530, 545, 1041, 2054, 2057, 4101, 4106, 4116, 4136, 4176, 4256, 4416, + 4736, 6656, 8195, 10753, 14336, 21506, 43012, 45056, 86024, 87296, 167936, 172048, 331776, 344096, 393216, + 524561, 524809, 525317, 526339, 567297, 589824, 655429, 655491, 659456, 688139, 688149, 688169, 688192, + 688209, 688289, 688449, 688769, 689409, 690689, 693249, 698401, 699009, 708609, 770049, 1015809, 1048770, + 1048866, 1049106, 1049610, 1050630, 1056771, 1064960, 1070082, 1310858, 1310982, 1311747, 1312768, 1376270, + 1376291, 1376320, 1397760, 1482754, 1574915, 1704067, 1835267, 1900555, 1916930, 1966099, 2031617, 196, 280, + 292, 385, 546, 577, 680, 1036, 1042, 1057, 2065, 4102, 4105, 5377, 8197, 8202, 8212, 8232, 8272, 8352, 8512, + 8832, 9472, 10754, 13312, 16387, 21508, 28672, 43016, 86032, 90112, 172064, 335872, 344128, 524481, 524577, + 524817, 525321, 526341, 528387, 545793, 655409, 655433, 655493, 655619, 663552, 688135, 688256, 698433, + 761857, 999425, 1049122, 1049618, 1050634, 1052678, 1059330, 1064963, 1081344, 1310818, 1310866, 1310986, + 1311238, 1312771, 1314816, 1376323, 1376384, 1392641, 1397763, 1398786, 1576963, 1704195, 1736711, 1835523, + 1900563, 1966115, 1998849, 2088963, 200, 386, 548, 1058, 16394, 16424, 16544, 17664, 18944, 57344, 180224, + 535041, 671744, 698497, 1052682, 1056774, 1353730, 1392648, 1836035 }; + +static int cbest_22[1023] = { + 1, 2, 2097153, 4, 8, 3145729, 16, 32, 64, 3670017, 128, 256, 512, 1024, 3932161, 2048, 4096, 8192, 16384, + 32768, 4063233, 65536, 131072, 262144, 524288, 1048576, 2097152, 4128769, 3, 6, 12, 24, 48, 96, 192, 384, + 768, 1536, 3072, 6144, 12288, 24576, 49152, 98304, 196608, 393216, 786432, 1572864, 3145728, 5, 2097155, 9, + 2097157, 10, 17, 2097161, 3145731, 3670016, 18, 33, 1835008, 2097169, 3145733, 20, 34, 65, 917504, 2097185, + 3145737, 4161537, 36, 66, 129, 458752, 2097217, 3145745, 3670019, 40, 68, 130, 257, 229376, 2097281, 3145761, + 3670021, 3932160, 72, 132, 258, 513, 114688, 2097409, 3145793, 3670025, 80, 136, 260, 514, 1025, 57344, + 1966080, 2097665, 3145857, 3670033, 144, 264, 516, 1026, 2049, 28672, 2098177, 3145985, 3670049, 3932163, + 160, 272, 520, 1028, 2050, 4097, 14336, 983040, 2099201, 3146241, 3670081, 3932165, 288, 528, 1032, 2052, + 4098, 7168, 8193, 2101249, 3146753, 3670145, 3932169, 4063232, 320, 544, 1040, 2056, 3584, 4100, 8194, 16385, + 491520, 2105345, 3147777, 3670273, 3932177, 4177921, 576, 1056, 1792, 2064, 4104, 8196, 16386, 32769, + 2113537, 3149825, 3670529, 3932193, 640, 896, 1088, 2080, 4112, 8200, 16388, 32770, 65537, 245760, 2031616, + 2129921, 3153921, 3671041, 3932225, 4063235, 448, 1152, 2112, 4128, 8208, 16392, 32772, 65538, 131073, + 2162689, 3162113, 3672065, 3932289, 4063237, 224, 1280, 2176, 4160, 8224, 16400, 32776, 65540, 122880, + 131074, 262145, 2228225, 3178497, 3674113, 3932417, 4063241, 112, 2304, 4224, 8256, 16416, 32784, 65544, + 131076, 262146, 524289, 1015808, 2359297, 3211265, 3678209, 3932673, 4063249, 4128768, 56, 2560, 4352, 8320, + 16448, 32800, 61440, 65552, 131080, 262148, 524290, 1048577, 2621441, 3276801, 3686401, 3933185, 4063265, 28, + 4608, 8448, 16512, 32832, 65568, 131088, 262152, 524292, 1048578, 3407873, 3702785, 3934209, 4063297, 14, + 5120, 8704, 16640, 30720, 32896, 65600, 131104, 262160, 507904, 524296, 1048580, 2097154, 3735553, 3936257, + 4063361, 4128771, 7, 13, 25, 49, 97, 193, 385, 769, 1537, 3073, 6145, 9216, 12289, 16896, 24577, 33024, + 49153, 65664, 98305, 131136, 196609, 262176, 393217, 524304, 786433, 1048584, 1572865, 2064384, 2097156, + 3801089, 3940353, 4063489, 4128773, 4186113, 26, 50, 98, 194, 386, 770, 1538, 3074, 6146, 10240, 12290, + 15360, 17408, 24578, 33280, 49154, 65792, 98306, 131200, 196610, 262208, 393218, 524320, 786434, 1048592, + 1572866, 2097159, 2097160, 2097165, 2097177, 2097201, 2097249, 2097345, 2097537, 2097921, 2098689, 2100225, + 2103297, 2109441, 2121729, 2146305, 2195457, 2293761, 2490369, 2883585, 3145730, 3948545, 4063745, 4128777, + 52, 100, 196, 388, 772, 1540, 3076, 6148, 12292, 18432, 24580, 33792, 49156, 66048, 98308, 131328, 196612, + 253952, 262272, 393220, 524352, 786436, 1048608, 1572868, 2097168, 3145732, 3964929, 4064257, 4128785, 11, + 104, 200, 392, 776, 1544, 3080, 6152, 7680, 12296, 20480, 24584, 34816, 49160, 66560, 98312, 131584, 196616, + 262400, 393224, 524416, 786440, 1048640, 1572872, 2097184, 3145735, 3145736, 3145741, 3145753, 3145777, + 3145825, 3145921, 3146113, 3146497, 3147265, 3148801, 3151873, 3158017, 3170305, 3194881, 3244033, 3342337, + 3538945, 3997697, 4065281, 4128801, 4161536, 19, 22, 208, 400, 784, 1552, 3088, 6160, 12304, 24592, 36864, + 49168, 67584, 98320, 132096, 196624, 262656, 393232, 524544, 786448, 1032192, 1048704, 1572880, 1835009, + 2097163, 2097216, 3145744, 3670018, 4067329, 4128833, 21, 35, 38, 44, 416, 800, 1568, 3104, 3840, 6176, + 12320, 24608, 40960, 49184, 69632, 98336, 126976, 133120, 196640, 263168, 393248, 524800, 786464, 917505, + 1048832, 1572896, 1835010, 2097171, 2097280, 3145760, 3670020, 4071425, 4128897, 37, 67, 70, 76, 88, 832, + 1600, 3136, 6208, 12352, 24640, 49216, 73728, 98368, 135168, 196672, 264192, 393280, 458753, 525312, 786496, + 917506, 1049088, 1572928, 1835012, 2097173, 2097187, 2097408, 3014657, 3145739, 3145792, 3670023, 3670024, + 3670029, 3670041, 3670065, 3670113, 3670209, 3670401, 3670785, 3671553, 3673089, 3676161, 3682305, 3694593, + 3719169, 3768321, 3866625, 4079617, 4129025, 4161539, 41, 69, 131, 134, 140, 152, 176, 1664, 1920, 3200, + 6272, 12416, 24704, 49280, 81920, 98432, 139264, 196736, 229377, 266240, 393344, 458754, 526336, 786560, + 917508, 1049600, 1572992, 1835016, 2097189, 2097219, 2097664, 2555905, 3145747, 3145856, 3670032, 4096001, + 4129281, 4161541, 42, 73, 133, 259, 262, 268, 280, 304, 352, 3328, 6400, 12544, 24832, 49408, 63488, 98560, + 114689, 147456, 196864, 229378, 270336, 393472, 458756, 516096, 528384, 786688, 917512, 1050624, 1573120, + 1835024, 2080768, 2097193, 2097221, 2097283, 2098176, 2326529, 3145749, 3145763, 3145984, 3670048, 3932162, + 4129793, 4161545, 74, 81, 137, 261, 515, 518, 524, 536, 560, 608, 704, 960, 6656, 12800, 25088, 49664, 57345, + 98816, 114690, 163840, 197120, 229380, 278528, 393728, 458760, 532480, 786944, 917520, 1052672, 1573376, + 1835040, 1966081, 2097225, 2097285, 2097411, 2099200, 2211841, 3145765, 3145795, 3146240, 3604481, 3670027, + 3670080, 3932164, 4130817, 4161553, 82, 138, 145, 265, 517, 1027, 1030, 1036, 1048, 1072, 1120, 1216, 1408, + 13312, 25600, 28673, 50176, 57346, 99328, 114692, 197632, 229384, 294912, 394240, 458768, 540672, 787456, + 917536, 1056768, 1573888, 1835072, 1966082, 2097233, 2097289, 2097413, 2097667, 2101248, 2154497, 3145769, + 3145797, 3145859, 3146752, 3375105, 3670035, 3670144, 3932167, 3932168, 3932173, 3932185, 3932209, 3932257, + 3932353, 3932545, 3932929, 3933697, 3935233, 3938305, 3944449, 3956737, 3981313, 4030465, 4132865, 4161569, + 4190209, 84, 146, 161, 266, 273, 480, 521, 1029, 2051, 2054, 2060, 2072, 2096, 2144, 2240, 2432, 2816, 14337, + 26624, 28674, 31744, 51200, 57348, 100352, 114696, 198656, 229392, 327680, 395264, 458784, 557056, 788480, + 917568, 983041, 1064960, 1574912, 1835136, 1966084, 2097297, 2097417, 2097669, 2098179, 2105344, 2125825, + 3145801, 3145861, 3145987, 3147776, 3260417, 3670037, 3670051, 3670272, 3932176, 4136961, 4161601, 4177920, + 148, 162, 274, 289, 522, 529, 1033, 2053, 4099, 4102, 4108, 4120, 4144, 4192, 4288, 4480, 4864, 5632, 7169, + 14338, 28676, 53248, 57352, 102400, 114704, 200704, 229408, 258048, 397312, 458816, 589824, 790528, 917632, + 983042, 1081344, 1576960, 1835264, 1966088, 2097313, 2097425, 2097673, 2098181, 2099203, 2111489, 2113536, + 3080193, 3145809, 3145865, 3145989, 3146243, 3149824, 3203073, 3670053, 3670083, 3670528, 3932192, 4145153, + 4161665, 164, 240, 276, 290, 321, 530, 545, 1034, 1041, 2057, 3585, 4101, 7170, 8195, 8198, 8204, 8216, 8240, + 8288, 8384, 8576, 8960, 9728, 11264, 14340, 28680, 57360, 106496, 114720, 204800, 229440, 401408, 458880, + 491521, 655360, 794624, 917760, 983044, 1040384, 1114112, 1581056, 1835520, 1966096, 2097441, 2097681, + 2098185, 2099205, 2101251, 2104321, 2129920, 3145873, 3145993, 3146245, 3146755, 3153920, 3174401, 3670057, + 3670085, 3670147, 3671040, 3899393, 3932171, 3932224, 4063234, 4161793, 168, 292, 322, 532, 546, 577, 1042, + 1057, 1793, 2058, 2065, 3586, 4105, 7172, 8197, 14344, 15872, 16387, 16390, 16396, 16408, 16432, 16480, + 16576, 16768, 17152, 17920, 19456, 22528, 28688, 57376, 114752, 212992, 229504, 409600, 459008, 491522, + 802816, 918016, 983048, 1179648, 1589248, 1836032, 1966112, 2097473, 2097697, 2098193, 2099209, 2100737, + 2101253, 2105347, 2162688, 2588673, 3145889, 3146001, 3146249, 3146757, 3147779, 3160065, 3162112, 3670089, + 3670149, 3670275, 3672064, 3784705, 3932179, 3932288, 4063236, 4162049, 4177923, 120, 296, 897, 1058, 1089, + 2081, 4106, 4113, 8201, 32774, 32780, 33536, 34304, 45056, 491524, 983056, 1605632, 1966144, 2031617, + 2098209, 2098945, 2099217, 2228224, 3146257, 3146761, 3178496, 3670153, 3670277, 3670531, 3932181, 3932416, + 4063329, 4063425, 4069377, 4075521 }; + +static int cbest_23[1023] = { + 1, 2, 4194320, 4, 2097160, 8, 1048580, 16, 524290, 32, 262145, 64, 128, 4325392, 256, 512, 2162696, 1024, + 2048, 1081348, 4096, 8192, 540674, 16384, 32768, 270337, 65536, 131072, 262144, 4329488, 524288, 2164744, + 1048576, 3, 1082372, 2097152, 4194321, 5, 2097161, 4194322, 6, 9, 1048581, 2097162, 4194304, 4194324, + 6291480, 10, 17, 524291, 541186, 1048582, 2097164, 4194328, 5242900, 12, 18, 33, 66, 132, 264, 528, 1056, + 2112, 4224, 8448, 16896, 33792, 67584, 135168, 270336, 3145740, 4718610, 20, 34, 65, 262147, 524294, 540672, + 1048588, 2097176, 2621450, 4194352, 4456465, 24, 36, 129, 262149, 270593, 524298, 1048596, 1081344, 1572870, + 2097192, 2359305, 4194384, 4325393, 40, 68, 130, 257, 262153, 524306, 1048612, 1310725, 2097224, 2162688, + 4194448, 4325394, 48, 72, 258, 513, 262161, 524322, 786435, 1048644, 2097288, 2162697, 4194576, 4325376, + 4325396, 6422552, 80, 136, 260, 514, 1025, 262177, 524354, 1048708, 2097416, 2162698, 4194832, 4325400, + 5373972, 6357016, 96, 144, 516, 1026, 2049, 262209, 524418, 1048836, 1081349, 2097672, 2162700, 4195344, + 4329616, 4849682, 160, 272, 520, 1028, 2050, 4097, 262273, 524546, 1049092, 1081350, 2098184, 3211276, + 4196368, 4325424, 4587537, 5275668, 192, 288, 1032, 2052, 4098, 8193, 262401, 524802, 540675, 1049604, + 2099208, 2162712, 2686986, 3178508, 4198416, 4325456, 320, 544, 1040, 2056, 4100, 8194, 16385, 262657, + 525314, 1050628, 1081356, 2101256, 2162728, 2424841, 4202512, 4325520, 4734994, 384, 576, 2064, 4104, 8196, + 16386, 32769, 263169, 526338, 540678, 1052676, 1081364, 1605638, 2105352, 2162760, 2164808, 2637834, 4210704, + 4325648, 640, 1088, 2080, 4112, 8200, 16388, 32770, 65537, 264193, 270339, 528386, 540682, 1056772, 1081380, + 1343493, 1589254, 2113544, 2162824, 4227088, 4325904, 4464657, 6488088, 768, 1152, 4128, 8208, 16392, 32772, + 65538, 131073, 266241, 270341, 532482, 540690, 1064964, 1081412, 2129928, 2162952, 2367497, 4259856, 4326416, + 1280, 2176, 4160, 8224, 16400, 32776, 65540, 131074, 270345, 540706, 802819, 1081476, 1318917, 2163208, + 4327440, 4329489, 5406740, 1536, 2304, 8256, 16416, 32784, 65544, 131076, 262146, 270353, 278529, 540738, + 557058, 794627, 1081604, 1082404, 1114116, 2163720, 2228232, 4329490, 4456464, 2560, 4352, 8320, 16448, + 32800, 65552, 131080, 262148, 270369, 270592, 294913, 524289, 540802, 541184, 589826, 1081860, 1082368, + 1179652, 2164736, 2359304, 3244044, 4329472, 4329492, 4333584, 4866066, 6426648, 3072, 4608, 16512, 32832, + 65568, 131088, 135296, 262152, 270401, 327681, 540930, 655362, 1310724, 2164745, 2166792, 4329496, 4341776, + 4718608, 5378068, 5120, 8704, 16640, 32896, 65600, 67648, 131104, 262160, 270465, 393217, 524292, 786434, + 1048577, 1083396, 2164746, 2170888, 2621448, 2703370, 4358160, 4595729, 4853778, 6359064, 6144, 9216, 33024, + 33824, 65664, 131136, 262176, 524296, 541202, 541698, 1048578, 1085444, 1572868, 2164748, 2179080, 4329520, + 4390928, 4591633, 5242896, 10240, 16912, 17408, 33280, 65792, 131200, 262208, 270849, 524304, 524352, 542722, + 1082373, 1089540, 1622022, 2097153, 2195464, 2433033, 3145736, 3213324, 4329552, 8456, 12288, 18432, 66048, + 131328, 262272, 271361, 524320, 544770, 786433, 1048584, 1048704, 1082374, 1097732, 2097154, 2164760, + 2689034, 4194323, 4587536, 5276692, 6291472, 7, 4228, 20480, 34816, 66560, 131584, 262400, 272385, 548866, + 1048592, 1351685, 1572866, 2097156, 2097163, 2097408, 2164776, 2293768, 2426889, 3179532, 4194305, 4194325, + 4329744, 6291481, 11, 2114, 24576, 36864, 132096, 262656, 270601, 274433, 524416, 541187, 1048583, 1048608, + 1082380, 1146884, 1310721, 2097165, 2424840, 3145732, 4194306, 4194326, 4194329, 4194816, 4330000, 4849680, + 5242901, 6291482, 6492184, 13, 19, 67, 133, 265, 529, 1057, 2113, 4225, 8449, 16897, 33793, 40960, 67585, + 69632, 133120, 135169, 263168, 524544, 573442, 811011, 1048640, 1082388, 1212420, 1606662, 2097166, 2097168, + 2164872, 2621442, 3145741, 4194308, 4194330, 4330512, 4718611, 4735506, 5242902, 6291464, 6291484, 6490136, + 14, 21, 35, 134, 266, 530, 1058, 4226, 8450, 16898, 33794, 49152, 67586, 73728, 135170, 264192, 270338, + 286721, 524295, 524800, 540673, 541190, 606210, 1048589, 1343492, 1344517, 2097177, 2097184, 2165000, + 2359297, 2621451, 2638346, 2686984, 3145742, 4194312, 4194332, 4194353, 4194386, 4194452, 4194584, 4195376, + 4196432, 4198544, 4202768, 4211216, 4228112, 4261904, 4331536, 4464656, 5242884, 5373968, 5410836, 7340060, + 22, 25, 37, 70, 268, 532, 1060, 2116, 8452, 16900, 33796, 67588, 81920, 135172, 139264, 266240, 270340, + 303105, 524299, 525312, 541194, 671746, 1048590, 1048597, 1048832, 1081345, 1082436, 1572871, 1589766, + 2097178, 2097193, 2097216, 2097226, 2097292, 2097688, 2098216, 2099272, 2101384, 2105608, 2114056, 2130952, + 2165256, 2232328, 2367496, 4194354, 4194385, 4456467, 4718594, 4718614, 4734992, 5242908, 6815770, 26, 38, + 41, 69, 74, 131, 140, 536, 1064, 2120, 4232, 16904, 33800, 67592, 98304, 135176, 147456, 262151, 270344, + 270595, 335873, 524307, 526336, 540676, 802818, 1048598, 1048613, 1048646, 1048844, 1049088, 1049108, + 1049636, 1050692, 1052804, 1057028, 1065476, 1081346, 1082500, 1116164, 1183748, 1318916, 1605636, 2097180, + 2097194, 2097225, 2097280, 2162689, 2165768, 2359307, 2621454, 2637832, 3211272, 4194336, 4194356, 4194449, + 4325395, 4337680, 4456449, 4456469, 4464913, 4718618, 4870162, 5275664, 5407764, 5767190, 6291512, 6422544, + 6553625, 28, 42, 49, 73, 82, 148, 259, 280, 1072, 2128, 4240, 8464, 33808, 67600, 135184, 163840, 262155, + 270352, 270597, 278528, 401409, 524302, 524323, 524422, 524554, 524818, 525346, 526402, 528384, 528514, + 532738, 540680, 541218, 558082, 591874, 659458, 794626, 803331, 1048614, 1048645, 1049600, 1082628, 1310727, + 1589252, 2097196, 2097289, 2162690, 2359309, 2367753, 3145756, 3178504, 3246092, 3670030, 4194360, 4194368, + 4194388, 4194450, 4194577, 4325377, 4325397, 4329620, 4345872, 4456473, 5242932, 5505045, 6291544, 6357008, + 6422553, 44, 50, 81, 98, 137, 164, 261, 296, 515, 560, 2144, 4256, 8480, 16928, 67616, 135200, 196608, + 262157, 262163, 262211, 262277, 262409, 262673, 263201, 264257, 266369, 270368, 279041, 294912, 295937, + 329729, 397313, 524310, 524355, 532480, 540688, 540736, 541250, 1048604, 1048709, 1050624, 1081352, 1081472, + 1082884, 1319173, 1572878, 2097228, 2097290, 2097417, 2097664, 2162692, 2162699, 2162944, 2168840, 2621466, + 3145772, 3245068, 3407885, 4194392, 4194432, 4194578, 4194833, 4325378, 4325398, 4325401, 4325888, 4362256, + 4599825, 4718642, 4980755, 5242964, 5373973, 6291608, 6357017, 6422554, 52, 76, 97, 138, 145, 196, 262, 328, + 517, 592, 1027, 1120, 4288, 8512, 16960, 33856, 135232, 262165, 262179, 270400, 270609, 327680, 524314, + 524326, 524419, 540704, 541314, 786439, 794883, 802817, 1048620, 1048710, 1048837, 1052672, 1081360, 1310733, + 1572886, 1605634, 2097208, 2097418, 2097673, 2098176, 2162701, 2172936, 2359321, 2621482, 2705418, 2883595, + 3145804, 3211268, 4194456, 4194560, 4194580, 4194834, 4195345, 4325380, 4325402, 4329617, 4395024, 4456497, + 4718674, 4849683, 4866578, 5243028, 5373974, 6291736, 6357018, 6422536, 6422556, 56, 84, 146, 161, 194, 273, + 392, 518, 521, 656, 1029, 1184, 2051, 2240, 8576, 17024, 33920, 67712, 262169, 262181, 270464, 270625, + 393216, 524330, 524358, 524547, 541442, 557056, 786443, 794625, 1048628, 1048652, 1048838, 1049093, 1056768, + 1081351, 1081376, 1084420, 1310741, 1343489, 1572902, 1589250, 1835015, 2097240, 2097420, 2097674, 2098185, + 2099200, 2162702, 2162704, 2181128, 2359337, 2621514, 2686978, 3145868, 3178500, 3211277, 4194416, 4194836, + 4195346, 4196369, 4325384, 4325404, 4325425, 4325458, 4325524, 4325656, 4326448, 4327504, 4329618, 4333840, + 4342288, 4359184, 4392976, 4456529, 4595728, 4718738, 5243156, 5275669, 5373956, 6291992, 6357000, 6357020, + 7471132, 162, 193, 289, 1030, 1312, 2053, 4099, 34048, 262185, 262213, 524338, 524362, 524803, 786451, + 1048716, 1049605, 1064960, 1086468, 1310757, 2097256, 2097304, 2097676, 2098186, 2099209, 2101248, 2162713, + 2424833, 2621578, 2703882, 3145996, 3178509, 4194480, 4198417, 4325426, 4456593, 4587539, 4718866, 4849666, + 6292504, 6426776, 7405596 }; + +static int cbest_24[1023] = { + 1, 2, 8388675, 4, 12583010, 8, 6291505, 16, 32, 64, 11534427, 128, 256, 8388674, 4194337, 14155886, 3, 512, + 8388673, 6, 12583011, 5, 1024, 10485843, 12, 6291504, 12583008, 9, 24, 2048, 3145752, 8388679, 10, 7077943, + 14680178, 48, 1572876, 13631594, 17, 4096, 8388683, 96, 786438, 12583014, 20, 6291507, 18, 33, 192, 8192, + 393219, 7340089, 8388691, 6815797, 11534426, 12583018, 384, 131073, 6291489, 6291509, 11927640, 34, 40, 65, + 16384, 262146, 8388707, 8585282, 12582978, 66, 768, 524292, 8388611, 8454211, 11534419, 11534425, 12583026, + 1048584, 6291513, 36, 129, 1536, 32768, 2097168, 4292641, 5767213, 80, 130, 4194336, 6291473, 11796569, + 12615778, 14155882, 132, 3072, 12058719, 12582946, 68, 257, 65536, 5963820, 8388803, 11534411, 11534431, + 14155887, 258, 6144, 196609, 393218, 6307889, 7077941, 160, 260, 8388672, 72, 264, 513, 12288, 131072, + 8388931, 10534995, 11272277, 14155878, 14155884, 786436, 8486979, 10485842, 12583138, 7, 516, 24576, 4194339, + 6291569, 11927641, 136, 320, 514, 520, 1025, 393217, 5242921, 7077939, 7077942, 8388677, 8389187, 8585283, + 12583009, 14418028, 13, 528, 49152, 1572872, 2981910, 8388678, 10485841, 11542619, 12583266, 14286959, + 15466612, 14, 4194341, 6291633, 12632162, 14680179, 25, 144, 1026, 1032, 2049, 98304, 262144, 786434, + 3145753, 8389699, 11534459, 13631595, 11, 26, 640, 1040, 3145744, 6291506, 8388682, 8388687, 11534363, + 11927642, 12583012, 12583522, 12681314, 13656170, 14024809, 28, 49, 1056, 196608, 1572877, 4194345, 6291761, + 7340088, 8388681, 11010135, 12583015, 14680176, 272, 1028, 2050, 4097, 1572868, 3145754, 3538971, 6291457, + 6316081, 6815793, 6815796, 8388699, 8390723, 10485827, 10485847, 13631586, 13631592, 22, 52, 97, 2064, + 786439, 4194305, 6291488, 6291508, 7209014, 8388690, 11534403, 12584034, 14155854, 21, 50, 56, 98, 1280, + 2080, 1490955, 1572878, 3670044, 4194353, 5963821, 6291497, 6292017, 6340657, 7733306, 8388643, 8388723, + 8781888, 9175109, 9961551, 12582914, 12582994, 12583019, 12583022, 14155902, 14159982, 15728762, 19, 193, + 288, 2052, 2112, 4098, 8193, 524288, 3145736, 3145756, 3407898, 4390944, 8392771, 10485851, 11534555, + 11796571, 12583016, 13893736, 14155874, 14352495, 15204470, 15532148, 44, 104, 393216, 2195472, 6291511, + 6291512, 7077927, 7340081, 8388689, 8388706, 8388739, 12582979, 12583034, 12585058, 14680162, 14680182, 112, + 196, 385, 4128, 1097736, 1835022, 4227105, 4292640, 5767209, 5767212, 6292529, 6828085, 7077937, 8388610, + 8388695, 8454210, 11534418, 11534423, 11534424, 12583027, 13631598, 35, 41, 194, 544, 2056, 2560, 4100, 4160, + 8194, 16385, 262147, 548868, 1703949, 2146320, 4259873, 6291472, 6291517, 7340091, 8388609, 8396867, 8519746, + 11534417, 11534683, 11927632, 12976225, 13369444, 14155822, 42, 67, 88, 100, 208, 769, 4224, 274434, 524293, + 1073160, 6291493, 6815799, 6946868, 7077951, 8388705, 8585280, 8650817, 10158158, 11546715, 12058715, + 12582976, 12587106, 14155880, 14286958, 14680186, 38, 134, 224, 386, 392, 770, 131075, 137217, 536580, + 786432, 917511, 1048585, 2883606, 3604507, 4194401, 5963816, 6291491, 6291537, 6293553, 7864381, 8389059, + 8454209, 10502227, 11272279, 11796568, 12583024, 12583074, 12615779, 14155883, 15401079, 37, 70, 268, 576, + 1537, 4104, 8196, 8256, 16386, 32769, 268290, 393223, 1048576, 2097169, 3866653, 6291515, 6307888, 7077911, + 7077940, 7079991, 7340073, 7340093, 7602235, 8388715, 8405059, 10485875, 10518611, 11534429, 11534939, + 11559003, 12058718, 12582947, 12582986, 12583030, 14680146, 81, 131, 176, 416, 536, 5120, 8320, 134145, + 524294, 786446, 2981908, 3153944, 3538970, 5767205, 6684722, 6815781, 8388802, 8389443, 8847424, 8912967, + 9134150, 9240645, 10485779, 11370581, 11534410, 11534430, 11927643, 12582944, 12591202, 12714083, 13631562, + 14024808, 82, 133, 262, 388, 448, 784, 1072, 1540, 3073, 8448, 131077, 1048586, 1441803, 1572892, 1576972, + 3473434, 4194465, 6295601, 7766074, 8388627, 8388801, 9437259, 11272273, 11534443, 11796561, 11927624, + 11927644, 12615776, 12845152, 13631610, 14156014, 14418030, 69, 84, 140, 200, 524, 1088, 1538, 2144, 4112, + 8200, 16388, 32770, 65537, 262150, 393227, 788486, 1490954, 1572864, 2097170, 3145784, 4292643, 4423712, + 5767215, 5898284, 6422576, 8388711, 8390211, 8421443, 8457283, 8585286, 11535451, 12058711, 12058717, + 12582982, 12583394, 13639786, 14696562, 15466614, 15564916, 76, 259, 352, 772, 832, 1048, 4288, 6145, 16512, + 394243, 786454, 3211288, 4194338, 5963812, 6291475, 6291481, 6291568, 6815805, 8388615, 8388930, 8454215, + 10534994, 11272276, 11534409, 11802713, 12599394, 13647978, 14155879, 14155885, 14876787, 74, 161, 261, 266, + 896, 1568, 2096, 3074, 3080, 8576, 10240, 16640, 131081, 655365, 1048588, 1310730, 1572908, 1605644, 1769485, + 2211856, 2621460, 3342361, 4194593, 5079079, 5242920, 6291697, 6299697, 7077938, 7143479, 7340057, 8388807, + 8388929, 8391747, 8455747, 8486978, 8781889, 11534415, 12583139, 12583778, 13107302, 14155876, 14156142, + 14418024, 14680114, 14745714, 73, 162, 265, 280, 1152, 4192, 8208, 12289, 16392, 16896, 17152, 32772, 65538, + 132097, 262154, 393235, 802822, 1736717, 2097152, 2097172, 2981906, 3145816, 3538969, 4243489, 4292645, + 5963822, 6029359, 6291553, 6815765, 7012404, 7209015, 8585290, 8585794, 8716353, 9109574, 10485971, 11536475, + 11928664, 12320861, 12582962, 12583136, 13008993, 13631530, 14024811, 14155894, 14162030, 14286955, 14352494, + 15466608, 164, 518, 704, 776, 1664, 6146, 8384, 34304, 133121, 196611, 401411, 524300, 786437, 786470, + 1105928, 1703948, 2949142, 3145728, 4194340, 6291477, 6291632, 6291889, 6307891, 6819893, 7078007, 7209012, + 7348281, 7733307, 8388619, 8388676, 8389186, 8394819, 8454219, 8454723, 10190926, 10534993, 11534451, + 11796553, 11796573, 12189790, 12584546, 12615782, 14418029, 138, 168, 400, 517, 532, 1792, 3076, 3136, 6160, + 16768, 24577, 33024, 68608, 131089, 135169, 264194, 745477, 851974, 1490953, 1572940, 4194849, 4292897, + 4390945, 5267497, 5636138, 6553651, 6823989, 7733304, 8388835, 8388935, 8455235, 8486977, 10321997, 10485840, + 11534395, 11542618, 12058703, 12582950, 12583106, 12583267, 12617314, 14156398, 14168174, 15466613, 16089208, + 137, 152, 321, 515, 521, 560, 1544, 2176, 8224, 12290, 16400, 20480, 32776, 33280, 33536, 65540, 131074, + 137216, 262162, 266242, 393251, 425987, 552964, 917510, 1572874, 2097176, 3145880, 3407896, 3604506, 4292649, + 4567075, 6291571, 6292273, 7372857, 8388939, 8400963, 8456259, 8519747, 8585298, 8589378, 10486099, 11538523, + 11927633, 12583142, 12583264, 12586082, 12616034, 12632163, 12779619, 12976224, 14155898, 148, 522, 529, + 1036, 1408, 3328, 6148, 33792, 49153, 67072, 196613, 270338, 393222, 458755, 524308, 528388, 786502, 1572873, + 2981911, 3866652, 3883037, 4194343, 4194344, 4554787, 5242913, 6291760, 6307873, 6307893, 7077925, 7077947, + 7078071, 8388867, 8389185, 8389698, 8454227, 8585281, 8781890, 9175111, 9273413, 10158159, 10510419, + 11010131, 11534458, 11534491, 12615786, 12616290, 12616546, 12648546, 12746851, 14073961, 14418020, 14680306, + 15, 324, 1064, 3584, 6272, 12320, 24578, 131105, 134144, 163841, 276482, 393221, 532484, 1048600, 1474571, + 1573004, 1835020, 3145748, 3506202, 4195361, 4292609, 4294689, 5767181, 6291456, 6293041, 6308017, 6316080, + 6324273, 6488112, 6815792, 7077923, 7077949, 8388686, 8389191, 8413251, 8601666, 9257029, 10928208, 11403348, + 11534347, 11534362, 11542611, 11542617, 11927672, 11960408, 12582954, 12583013, 12583523, 12589154, 12616802, + 12681315, 13631722, 13656171, 13893738, 14155846, 14156910, 14286951, 14286957, 15401078, 15532150, 145, 322, + 328, 1027, 1033, 1120, 1552, 2304, 12292, 16416, 32784, 65544, 66048, 98305, 131076, 262145, 262178, 393283, + 540676, 786435, 1056776, 1441802, 2818069, 3146008, 4194304, 4194321, 4194349, 4292657, 5242923, 5767229, + 5771309, 5964332, 6291601, 6291635, 6308145, 6946869, 7209010, 7340153, 7782458, 8388680, 8388685, 8388811, + 8389195, 8470595, 8585314, 8618050, 10059855, 10485835, 10485845, 10486355, 10534979, 10534999, 10584147, + 11010134, 11272261, 11534361, 11665498, 11798617, 11927576, 11927634, 11993176, 12583270, 12615746, 12632160, + 14155790, 14155850, 14155870, 14680177, 15827066, 146, 276, 336, 641, 800, 1034, 2816, 6656, 49154, 66560, + 196617, 197121, 524324, 720901, 786442, 786566, 3158040, 3670040, 5963817, 6291637, 6292016, 6294577, + 6307897, 6308657, 6340656, 6815861, 7078199, 8389203, 8390722, 8454243, 8486983, 8585218, 8847425, 9134151, + 10485846, 10535123, 12583274, 12615794, 13631587, 14159978 }; + +static int cbest_25[1023] = { + 1, 2, 16777220, 4, 8388610, 8, 4194305, 16, 32, 18874372, 64, 128, 9437186, 256, 512, 4718593, 1024, 2048, + 4096, 19136516, 8192, 16384, 32768, 9568258, 65536, 131072, 262144, 4784129, 524288, 1048576, 2097152, + 4194304, 19169284, 8388608, 3, 9584642, 16777216, 16777221, 5, 8388611, 16777222, 6, 9, 18, 36, 72, 144, 288, + 576, 1152, 2304, 4608, 9216, 18432, 36864, 73728, 147456, 294912, 589824, 1179648, 2359296, 4718592, + 25165830, 10, 17, 4194307, 8388614, 9437184, 16777228, 20971525, 12, 33, 4194309, 4792321, 8388618, 12582915, + 16777236, 18874368, 18874373, 20, 34, 65, 4194313, 8388626, 16777252, 18874374, 24, 66, 129, 4194321, + 8388642, 9437187, 16777284, 27262982, 40, 68, 130, 257, 4194337, 8388674, 16777348, 18874380, 23068677, + 26214406, 48, 132, 258, 513, 4194369, 8388738, 9437190, 16777476, 18874388, 80, 136, 260, 514, 1025, 4194433, + 4718595, 8388866, 9437194, 13631491, 16777732, 18874404, 19173380, 21495813, 96, 264, 516, 1026, 2049, + 4194561, 4718597, 8389122, 9437202, 13107203, 16778244, 18874436, 160, 272, 520, 1028, 2050, 4097, 4194817, + 4718601, 4784128, 8389634, 9437218, 9568256, 16779268, 18874500, 19136512, 19136517, 28311558, 192, 528, + 1032, 2052, 4098, 8193, 2392064, 4195329, 4718609, 8390658, 9437250, 16781316, 18874628, 19136518, 320, 544, + 1040, 2056, 4100, 8194, 16385, 1196032, 4196353, 4718625, 8392706, 9437314, 16785412, 18874884, 23592965, + 27525126, 384, 1056, 2064, 4104, 8196, 16386, 32769, 598016, 4198401, 4718657, 8396802, 9437442, 9568259, + 9586690, 16793604, 18875396, 19136524, 23330821, 640, 1088, 2080, 4112, 8200, 16388, 32770, 65537, 299008, + 4202497, 4718721, 8404994, 9437698, 14155779, 16809988, 18876420, 19136532, 26345478, 768, 2112, 4128, 8208, + 16392, 32772, 65538, 131073, 149504, 4210689, 4718849, 8421378, 9438210, 9568262, 16842756, 18878468, + 19136548, 1280, 2176, 4160, 8224, 16400, 32776, 65540, 74752, 131074, 262145, 4227073, 4719105, 8454146, + 9439234, 9568266, 13762563, 16908292, 18882564, 19136580, 1536, 4224, 8256, 16416, 32784, 37376, 65544, + 131076, 262146, 524289, 4259841, 4719617, 4784131, 8519682, 9441282, 9568274, 17039364, 18890756, 19136644, + 21561349, 28573702, 2560, 4352, 8320, 16448, 18688, 32800, 65552, 131080, 262148, 524290, 1048577, 4325377, + 4720641, 4784133, 4793345, 8650754, 9445378, 9568290, 13172739, 17301508, 18907140, 19136772, 28442630, 3072, + 8448, 9344, 16512, 32832, 65568, 131088, 262152, 524292, 1048578, 2097153, 4456449, 4722689, 4784137, + 8912898, 9453570, 9568322, 17825796, 18939908, 19137028, 23855109, 4672, 5120, 8704, 16640, 32896, 65600, + 131104, 262160, 524296, 1048580, 2097154, 4726785, 4784145, 9469954, 9568386, 19005444, 19137540, 19169280, + 19169285, 2336, 6144, 16896, 33024, 65664, 131136, 262176, 524304, 1048584, 2097156, 4194306, 4734977, + 4784161, 5242881, 9502722, 9568514, 9584640, 10485762, 19138564, 19169286, 20971524, 23658501, 1168, 10240, + 17408, 33280, 65792, 131200, 262208, 524320, 1048592, 2097160, 4194308, 4751361, 4784193, 4792320, 6291457, + 8388609, 9568770, 12582914, 14286851, 19140612, 19398660, 27557894, 584, 12288, 33792, 66048, 131328, 262272, + 524352, 1048608, 2097168, 4194312, 4784257, 9569282, 9699330, 14221315, 19144708, 19169292, 19922948, + 23363589, 25165828, 292, 20480, 34816, 66560, 131584, 262400, 524416, 1048640, 2097184, 2396160, 4194320, + 4784385, 4849665, 8388612, 8388624, 9570306, 9584643, 9961474, 16777217, 19152900, 19169300, 19173892, 146, + 24576, 67584, 132096, 262656, 524544, 1048704, 2097216, 4194336, 4784641, 4980737, 8388616, 9572354, + 12582913, 16777218, 16777223, 16777248, 19169316, 23068676, 26361862, 28704774, 7, 19, 37, 73, 145, 289, 577, + 1153, 2305, 4609, 9217, 18433, 36865, 40960, 69632, 73729, 133120, 147457, 263168, 294913, 524800, 589825, + 1048832, 1179649, 1198080, 2097280, 2359297, 4194368, 4785153, 9576450, 9584646, 11534338, 19169348, + 19202052, 25165826, 25165831, 11, 38, 74, 290, 578, 1154, 2306, 4610, 9218, 18434, 36866, 49152, 73730, + 135168, 147458, 264192, 294914, 525312, 589826, 1049088, 1179650, 2097408, 2359298, 4194432, 4718594, + 4786177, 5767169, 8388615, 8388640, 9437185, 9584650, 13631490, 13778947, 16777224, 16777229, 16777238, + 16777292, 16777364, 16777508, 16777796, 16778372, 16779524, 16781828, 16786436, 16795652, 16814084, 16850948, + 16924676, 17072132, 17367044, 17956868, 19169412, 19267588, 20971521, 21495812, 27262980, 28606470, 13, 22, + 76, 148, 580, 1156, 2308, 4612, 9220, 18436, 36868, 73732, 81920, 139264, 147460, 266240, 294916, 526336, + 589828, 599040, 1049600, 1179652, 2097664, 2359300, 4194560, 4718596, 4788225, 6815745, 8388619, 8388646, + 8388672, 8388682, 8388754, 8388898, 8389186, 8389762, 8390914, 8393218, 8397826, 8407042, 8425474, 8462338, + 8536066, 8683522, 8978434, 9584658, 9601026, 10747906, 13107202, 16777230, 16777232, 16777237, 18874369, + 19169540, 20971527, 23920645, 26214404, 14, 21, 26, 35, 44, 152, 296, 1160, 2312, 4616, 9224, 18440, 36872, + 73736, 98304, 147464, 270336, 294920, 528384, 589832, 1050624, 1179656, 2098176, 2359304, 4194311, 4194323, + 4194341, 4194377, 4194449, 4194593, 4194816, 4194881, 4195457, 4196609, 4198913, 4203521, 4212737, 4231169, + 4268033, 4341761, 4489217, 4718600, 4792323, 5373953, 6553601, 8388627, 8388736, 9437188, 9437200, 9584674, + 9633794, 16777253, 18874370, 18874375, 18874400, 19169796, 19660804, 21569541, 23887877, 25165838, 28459014, + 29360135, 25, 52, 67, 88, 304, 592, 2320, 4624, 9232, 18448, 36880, 73744, 147472, 163840, 278528, 294928, + 299520, 532480, 589840, 1052672, 1179664, 2099200, 2359312, 4194315, 4195328, 4718608, 4792325, 4800513, + 8388622, 8388643, 8388864, 9437192, 9584706, 9586946, 12582919, 13180931, 13631489, 16777254, 16777280, + 16777285, 19170308, 20185092, 20971533, 25165846, 27262978, 27262983, 41, 50, 69, 104, 131, 176, 608, 1184, + 4640, 9248, 18464, 36896, 73760, 147488, 196608, 294944, 540672, 589856, 1056768, 1179680, 2101248, 2359328, + 4194317, 4196352, 4718624, 4792329, 4816897, 8388630, 8388675, 8389120, 9584770, 9830402, 12582923, 13107201, + 14352387, 16777244, 16777286, 16777344, 16777349, 18874376, 18874381, 18874390, 18874444, 18874516, 18874660, + 18874948, 18875524, 18876676, 18878980, 18883588, 18892804, 18911236, 18948100, 19021828, 19171332, 19464196, + 20054020, 20971541, 23068673, 23592964, 25165862, 26214402, 26214407, 28, 42, 49, 70, 82, 100, 133, 208, 259, + 352, 1216, 2368, 9280, 18496, 36928, 73792, 147520, 149760, 294976, 327680, 557056, 589888, 1064960, 1179712, + 2105344, 2359360, 4194325, 4194339, 4198400, 4718656, 4792337, 8388634, 8388739, 8389632, 9437191, 9437216, + 9584898, 10092546, 12582931, 16777260, 16777350, 16777472, 16777477, 18874382, 18874384, 18874389, 20971557, + 23068679, 23330820, 25165894, 28311556, 81, 134, 137, 164, 200, 261, 416, 515, 704, 2432, 4736, 18560, 36992, + 73856, 147584, 295040, 393216, 589952, 1081344, 1179776, 2113536, 2359424, 4194329, 4194371, 4202496, + 4718720, 4792353, 4915201, 8388650, 8388678, 8388867, 8390656, 9437195, 9437222, 9437248, 9437258, 9437330, + 9437474, 9437762, 9438338, 9439490, 9441794, 9446402, 9455618, 9474050, 9510914, 9585154, 9732098, 10027010, + 11796482, 12582947, 14155778, 14303235, 16777268, 16777478, 16777728, 16777733, 18874405, 19173376, 19173381, + 19177476, 20971589, 21495809, 23666693, 25165958, 27262990, 31457287, 97, 138, 262, 265, 274, 328, 400, 517, + 832, 1027, 1408, 4864, 9472, 37120, 73984, 74880, 147712, 295168, 590080, 655360, 1114112, 1179904, 2129920, + 2359552, 4194345, 4194373, 4194435, 4210688, 4718848, 4792385, 5046273, 8388658, 8388742, 8389123, 8392704, + 9437203, 9437312, 9585666, 11665410, 12582979, 16777300, 16777356, 16777734, 16778240, 16778245, 18874406, + 18874432, 18874437, 19173382, 19185668, 20971653, 21495815, 23068685, 25166086, 26214414, 27262998, 27525124, + 30408711, 56, 84, 98, 140, 161, 266, 518, 521, 530, 656, 800, 1029, 1664, 2051, 9728, 18944, 74240, 147968, + 295424, 590336, 786432, 1180160, 2162688, 2359808, 4194353, 4194437, 4194563, 4227072, 4718599, 4718611, + 4718629, 4718665, 4718737, 4718881, 4719104, 4719169, 4720897, 4723201, 4727809, 4737025, 4755457, 4792449, + 4866049, 5013505, 5898241, 7077889, 8388690, 8388870, 8389635, 8396800, 9437198, 9437219, 9437440, 9568257, + 12583043, 13631495, 13762562, 14229507, 16777316, 16777484, 16778246, 16779264, 16779269, 18874396, 18874438, + 18874496, 18874501, 19136513, 20971781, 23068693, 25166342, 26214422, 27263014, 27561990, 28311554, 28311559, + 28737542, 29884423 }; + +static int cbest_26[1023] = { + 1, 2, 33554467, 4, 50331698, 8, 25165849, 16, 32, 64, 46137391, 128, 256, 56623156, 512, 33554466, 16777233, + 3, 1024, 28311578, 33554465, 6, 50331699, 5, 41943083, 12, 2048, 25165848, 50331696, 9, 24, 12582924, + 33554471, 10, 4096, 14155789, 58720314, 48, 6291462, 54526006, 17, 33554475, 96, 8192, 3145731, 50331702, 20, + 25165841, 25165851, 18, 33, 192, 29360157, 33554483, 50331682, 34, 16384, 27263003, 33554435, 35127330, + 46137387, 46137390, 50331706, 384, 25165853, 40632357, 40, 65, 66, 768, 32768, 17563665, 25165833, 46137389, + 56623158, 68, 1048577, 50331666, 36, 129, 1536, 2097154, 23068695, 33554531, 46137383, 48234541, 80, 130, + 65536, 4194308, 28311579, 34078755, 47185966, 56623152, 56623157, 132, 3072, 8388616, 28311576, 136, 257, + 14155788, 16777232, 33554595, 6144, 131072, 42336299, 45088808, 50331762, 50593842, 53870641, 160, 260, + 25165881, 72, 258, 264, 513, 12288, 1572865, 3145730, 33554723, 272, 262144, 7077894, 23592983, 25296921, + 33554464, 50331826, 57671733, 24576, 22544404, 25165913, 47710254, 61866041, 320, 514, 520, 1025, 6291460, + 33554979, 34340899, 41943082, 46137407, 7, 528, 49152, 524288, 16777235, 46137359, 50331954, 544, 3145729, + 3538947, 20971541, 25165977, 33554469, 35127331, 50331697, 54722614, 56623140, 13, 144, 516, 1026, 2049, + 98304, 11272202, 12582920, 28311570, 33554470, 33555491, 41943081, 45350952, 56623164, 14, 640, 1040, + 1048576, 14155785, 16777237, 46202927, 50332210, 50724914, 58720315, 25, 1056, 196608, 6291458, 12582925, + 25166105, 27263001, 41943075, 44040233, 54526002, 54526007, 11, 26, 1028, 1088, 2050, 4097, 16777217, + 23855127, 25165825, 25165840, 25165850, 28311582, 33554474, 33554479, 33556515, 46137455, 50331700, 51118130, + 60489787, 62390329, 28, 49, 393216, 5636101, 6291463, 16777241, 29360156, 33554473, 35323938, 46137379, + 50331703, 50332722, 56623124, 58720312, 50, 1280, 2080, 12582916, 12582926, 22675476, 25165845, 25166361, + 25362457, 27263002, 28311562, 33554451, 33554491, 36700192, 39845925, 40632359, 41943087, 47185967, 50331650, + 50331690, 54526004, 22, 52, 97, 288, 1032, 2052, 2112, 4098, 8193, 786432, 14155781, 14155791, 18350096, + 25165852, 27361307, 29360153, 33554482, 33558563, 46137385, 46137519, 50331683, 56623154, 56655924, 58720306, + 60817464, 64487487, 21, 56, 2176, 2097152, 9175048, 14680078, 23068693, 25559065, 33554434, 33554499, + 46137386, 50331707, 50331710, 50333746, 62914622, 19, 100, 193, 1572864, 4587524, 13631501, 17563664, + 25165832, 25165843, 25166873, 28311577, 33554433, 40632353, 40632356, 45088809, 50331704, 53870640, 55574583, + 35, 44, 98, 104, 2056, 2560, 4100, 4160, 8194, 16385, 2293762, 8781832, 17661969, 25165855, 33554481, + 33562659, 36372513, 45482024, 46137647, 48234543, 50331680, 53477425, 56623220, 58720318, 42, 70, 112, 385, + 4224, 1146881, 4390916, 7340039, 11337738, 16777265, 23068694, 30408732, 33554487, 35127328, 46137388, + 50331686, 50335794, 56623159, 57147444, 38, 41, 140, 194, 200, 386, 4352, 2195458, 25165865, 25167897, + 28327962, 29360149, 29360159, 33554659, 41943099, 50331667, 50331730, 57671732, 58720298, 67, 88, 208, 280, + 576, 769, 2064, 4104, 8196, 16386, 32769, 1097729, 3145735, 23068691, 27262995, 28311610, 33554443, 33554530, + 33570851, 37224480, 40370213, 41943051, 46137382, 46137903, 46235695, 47710255, 48234537, 48234540, 50331664, + 54525990, 56623284, 61866040, 69, 84, 134, 224, 560, 5120, 8320, 3145728, 3538946, 4194304, 6291470, + 11534347, 16777297, 17039377, 20316178, 31457311, 33554529, 33554851, 34078754, 45088810, 46137381, 47185962, + 50339890, 53870643, 54526014, 56623153, 61341752, 37, 76, 196, 268, 400, 772, 1120, 1537, 8448, 2097155, + 7077892, 12582940, 15204366, 17301521, 18612240, 22544405, 23592981, 25165837, 25169945, 26935320, 34127907, + 34603042, 46137399, 46333999, 47235118, 64749631, 81, 131, 176, 416, 536, 770, 2240, 4112, 8200, 8704, 16388, + 32770, 65537, 1769473, 3145739, 4194309, 5668869, 14155784, 14155805, 17563667, 22741012, 25165835, 25165880, + 27263007, 28311642, 28573722, 33554439, 33554594, 33555235, 33587235, 35127334, 35651617, 46138415, 50331890, + 56098871, 56623412, 63799358, 65798204, 82, 133, 138, 168, 388, 448, 1072, 3073, 4480, 1048579, 6291478, + 8388617, 9306120, 14163981, 16777361, 24117270, 25165873, 28835866, 29360141, 33554535, 33554593, 34078753, + 34103331, 42074155, 42336298, 45350953, 47185964, 50331674, 50331763, 50348082, 50593843, 56623160, 57671735, + 58720282, 60293179, 137, 152, 800, 1538, 1544, 2144, 8960, 10240, 16640, 6291456, 12582956, 23592982, + 25165945, 25174041, 25296920, 27262987, 28311568, 30933020, 33556003, 39321638, 41943147, 42205227, 42385451, + 46137403, 48234533, 50331760, 50332082, 51740723, 53739569, 54525974, 61866043, 262, 352, 832, 1152, 4128, + 4288, 6145, 8208, 16392, 16896, 17920, 32772, 65538, 131073, 3145747, 3538945, 4194310, 4653060, 5636100, + 7602183, 10158089, 12648460, 14155821, 17563669, 25165912, 28311571, 28311580, 28311706, 30670876, 33554547, + 33554722, 33620003, 35127338, 37748775, 46139439, 47185958, 49283116, 50331746, 51380275, 56623668, 56672308, + 57409588, 74, 161, 261, 276, 336, 392, 896, 3074, 8576, 17408, 35840, 1048581, 6291494, 6324230, 7077890, + 8388608, 8388618, 11272200, 16777489, 23592979, 25166041, 33554599, 33557539, 40632365, 42336297, 44826665, + 50331670, 50331827, 50332466, 50364466, 50593840, 50618418, 52428848, 56623136, 56623166, 57671729, 60489786, + 62390328, 73, 259, 265, 304, 1540, 1600, 3088, 12289, 17152, 71680, 2097158, 2326530, 2818050, 3162115, + 12058635, 12582988, 13467660, 14155780, 14155790, 14286861, 16777234, 17563649, 21168149, 22544400, 25165883, + 25182233, 26214424, 33554563, 33554603, 34439203, 35323939, 41943211, 46137375, 47710250, 50331766, 50331824, + 54591542, 56623142, 56721460, 58851386, 164, 266, 273, 524, 704, 776, 1664, 6146, 8224, 16400, 20480, 32776, + 33280, 34304, 65540, 131074, 143360, 262145, 3145763, 5242885, 7077895, 10485770, 11370506, 11796491, + 12582912, 13107212, 14155853, 14417933, 17563673, 19660819, 20971540, 25165976, 25166233, 28311583, 28311834, + 33554721, 33554978, 33560611, 33685539, 34078759, 34340898, 35127346, 36388897, 36700193, 37355552, 42336291, + 45088800, 45350954, 46137351, 46137406, 46141487, 50333234, 50606130, 54657078, 56624180, 58720378, 61603896, + 162, 552, 672, 1792, 3076, 24577, 33792, 68608, 286720, 1048585, 1163265, 1409025, 6291526, 6553606, 8388620, + 13631500, 14155777, 15466510, 16777745, 17170449, 23068679, 23617559, 23855125, 25165897, 25165969, 28311554, + 33554727, 35127298, 35135522, 36175905, 40632373, 40636453, 46137355, 46137358, 46137423, 50331955, 50397234, + 54526070, 56623108, 56623148, 59244602, 64487486, 321, 515, 521, 608, 3200, 6176, 12290, 34816, 137216, + 573440, 1572867, 2097162, 3276803, 6291461, 6815750, 12583052, 15335438, 16777236, 20971537, 22675477, + 23068703, 24641558, 25165915, 25166617, 25198617, 28311563, 29360189, 33554468, 33554539, 33554731, 33566755, + 40632325, 41943339, 44040235, 46137357, 46137451, 47710252, 50331830, 50334770, 54722610, 54722615, 56623126, + 56623141, 148, 274, 322, 522, 529, 784, 1048, 1408, 2304, 3328, 6148, 8256, 16416, 32784, 49153, 65544, + 131076, 262146, 274432, 524289, 1146880, 3145795, 3407875, 4194316, 7340038, 14155917, 17567761, 18350097, + 18677776, 25165917, 25166104, 25296913, 25296923, 25309209, 27263000, 27263035, 27295771, 28311560, 28311574, + 28312090, 28336154, 28704794, 29425693, 32899102, 33554739, 33554977, 33555490, 33816611, 34078763, 34340897, + 37093408, 41943080, 42336303, 45088812, 46137405, 46145583, 50331794, 50331834, 50331938, 50593846, 53870645, + 55574582, 56229943, 56623165, 56625204, 58720442, 62390331, 63701054, 65929276, 518, 545, 1104, 1344, 3080, + 3584, 24578, 40960, 66560, 548864, 1048593, 3670019, 6291590, 12582922, 16777216, 16778257, 22544406, + 23855126, 25165824, 25165885, 25165905, 25166097, 25167385, 27328539, 27361305, 31195164, 33579043, 35192866, + 39583782, 40632355, 44138537, 45482025, 46202923, 46202926, 47710246, 50331952, 50332211, 50337842, 50462770, + 50724915, 51904563, 53477424, 54526000, 54526134, 60424251, 61866033, 145, 328, 517, 532, 546, 1027, 1216, + 1552, 6400, 12292, 12352, 67584, 98305, 1097728, 1572869, 2097170, 3145734, 6733830, 11272203, 12582921, + 12583180, 14155787, 14680076, 16777225, 16777239, 16777240, 25165979, 25231385, 25303065, 28360730, 29360221, + 29622301, 33554787, 33554947, 33554987, 35127329, 35258402, 36700194, 38633511, 39452710, 39845927, 40697893, + 41943074, 41943079, 41943595, 42139691, 43384874, 44040232, 46137515, 46137583, 48234557, 50331958, 50593826, + 50774066, 51216434, 51642419, 53870625, 54526003, 54722612, 54747190, 59424826, 15, 641, 6152, 6656, 49154, + 69632, 131080, 4194324, 11534346, 14156045, 17596433, 25168921, 25296925, 25362456, 27263067, 33556514, + 35389474, 41943073, 50331701, 50331770, 50332194, 50343986, 50593850, 60817466 }; + +static int cbest_27[1023] = { + 1, 2, 67108883, 4, 100663322, 8, 50331661, 16, 32, 92274709, 64, 128, 113246233, 256, 512, 67108882, + 33554441, 3, 1024, 67108881, 123731999, 6, 100663323, 5, 2048, 83886103, 12, 50331660, 100663320, 9, 24, + 4096, 25165830, 67108887, 109051928, 10, 117440542, 48, 12582915, 50331657, 17, 8192, 54525964, 67108891, + 100663314, 128974876, 18, 96, 67108867, 92274711, 100663326, 20, 50331663, 73400338, 92274708, 113246232, 33, + 192, 16384, 27262982, 58720271, 34, 50331653, 92274705, 36, 384, 36700169, 46137354, 100663306, 40, 65, + 32768, 13631491, 56623116, 67108915, 66, 768, 96469012, 113246235, 68, 23068677, 64487438, 72, 129, 1536, + 65536, 67108947, 80, 4194305, 28311558, 73924626, 100663354, 132, 3072, 8388610, 48234506, 50331677, + 85458967, 123731998, 130, 136, 257, 131072, 16777220, 67109011, 69206035, 78643217, 144, 6144, 33554440, + 92274717, 100663386, 160, 14155779, 36962313, 50331693, 92274693, 258, 264, 513, 12288, 262144, 24117253, + 67109139, 101711898, 113246225, 272, 6291457, 12582914, 32243719, 100663450, 109838360, 113246237, 288, + 24576, 50331725, 67108880, 260, 320, 514, 1025, 524288, 50855949, 61865999, 67109395, 528, 49152, 25165828, + 70254611, 74186770, 83886102, 92274741, 100663578, 106430491, 123731995, 7, 544, 33554443, 50331789, + 79167505, 113246217, 123731997, 516, 576, 1026, 2049, 98304, 1048576, 12582913, 41943051, 54525965, 54919180, + 67108885, 67109907, 73400339, 83886099, 85590039, 100663321, 109051930, 13, 640, 33554433, 50331656, + 67108886, 83886101, 92274773, 92536853, 100663834, 109051929, 14, 26, 1056, 196608, 13631490, 33554445, + 50331649, 50331917, 83230736, 102236186, 117440543, 25, 52, 520, 1028, 1088, 2050, 4097, 2097152, 6815745, + 25165826, 25165831, 37093385, 67110931, 88080406, 92274707, 98041876, 123731991, 128974878, 11, 104, 1152, + 393216, 23068676, 27262980, 50331659, 50331662, 58720269, 67108875, 67108890, 67108895, 79691792, 92274837, + 94371861, 100663298, 100663315, 100663318, 100663324, 100664346, 103809050, 113246265, 117440538, 128974877, + 22, 28, 49, 208, 1280, 11534338, 27459590, 39845896, 46137355, 50332173, 58720270, 67108866, 67108889, + 92274710, 96469013, 100663312, 100663327, 113246234, 117440540, 44, 416, 1032, 2052, 2112, 4098, 8193, + 786432, 4194304, 5767169, 19922948, 44040203, 46137352, 50331652, 51118093, 54525960, 56623117, 67108865, + 67108899, 67112979, 109903896, 113377305, 120324126, 125829148, 128974872, 19, 88, 97, 832, 2176, 9961474, + 13631489, 36700168, 70516755, 92274965, 100665370, 106692635, 113246297, 121634847, 21, 38, 50, 56, 176, + 1664, 2304, 1572864, 4980737, 18350084, 29360135, 33554457, 50332685, 51904525, 64487439, 73924627, 92274704, + 109051920, 123731983, 76, 193, 352, 1040, 2056, 2560, 3328, 4100, 8194, 16385, 9175042, 27262978, 27262983, + 41615368, 49020938, 54525966, 58720267, 64487436, 67108871, 67117075, 73400336, 83886111, 90177558, + 100663307, 109051932, 114294809, 117440534, 35, 98, 152, 194, 704, 4224, 6656, 3145728, 4587521, 13729795, + 14155778, 50331669, 62914574, 67108914, 67108979, 69992467, 81788944, 83886087, 89128982, 92275221, 96469014, + 100663304, 100663338, 100667418, 113246361, 115343385, 37, 42, 70, 112, 304, 385, 1408, 4352, 13312, + 12582919, 24117252, 28311556, 33554473, 48234507, 50331655, 50333709, 54525956, 67108913, 80740368, 85655575, + 92274713, 92667925, 95420437, 128974868, 41, 140, 608, 2064, 2816, 4104, 4608, 8196, 16386, 26624, 32769, + 6291456, 7077889, 8388608, 25165838, 32243718, 40894472, 48234504, 54951948, 56623112, 67109075, 67125267, + 69599251, 102367258, 127926300, 67, 100, 280, 388, 769, 1216, 5120, 5632, 53248, 12058626, 40370184, + 45088779, 50331673, 50331676, 67108946, 92275733, 93061141, 96469008, 100663310, 100671514, 104071194, + 109051912, 113246224, 113246489, 123732031, 131596317, 69, 74, 84, 224, 386, 560, 2432, 8448, 11264, 106496, + 12582923, 20447236, 23068673, 31457287, 33554505, 36700171, 44564491, 50335757, 58720263, 60162063, 64487434, + 67108919, 67108945, 67109267, 69402643, 73400342, 92274719, 100663355, 100663418, 113246236, 117440526, + 123797535, 73, 196, 1120, 1537, 2080, 4112, 4864, 8200, 8704, 16388, 22528, 32770, 65537, 212992, 6029313, + 14155777, 20185092, 24510469, 25165846, 56623118, 67108923, 67141651, 78643219, 83886135, 85458966, 92274695, + 99352596, 100663346, 100663352, 102105114, 113246239, 81, 134, 770, 776, 2240, 9216, 9728, 45056, 425984, + 10223618, 20807684, 28311554, 28311559, 34603017, 36700161, 36962312, 46137346, 50331689, 50331692, 50331709, + 67109010, 67109651, 69206034, 73973778, 78643216, 91226134, 92274689, 92276757, 100663514, 100679706, + 113246227, 113246745, 120455198, 123732063, 128974860, 133, 148, 168, 448, 3073, 4480, 10240, 19456, 90112, + 851968, 8388611, 10092546, 12582912, 12582931, 23068679, 32243717, 33554569, 35651593, 36700173, 46137358, + 50339853, 51183629, 56623108, 63963150, 67108931, 67108951, 70647827, 71303186, 73400346, 73924624, 74186771, + 82837520, 85458963, 92274701, 92274716, 100663387, 101908506, 106430490, 113442841, 114819097, 123731994, + 124256287, 131, 137, 200, 1538, 4128, 8208, 8960, 16392, 16896, 32772, 38912, 65538, 131073, 180224, 1703936, + 5111809, 13631495, 16121859, 16777216, 16777221, 18481156, 25165862, 27262990, 27475974, 39321608, 50331679, + 50331757, 52035597, 54525980, 67108955, 67110419, 67174419, 73400322, 75497489, 83886167, 85458965, 89653270, + 92274692, 100663358, 100663378, 100663384, 100663706, 109051960, 109936664, 113246216, 123731996, 124780575, + 82, 138, 145, 268, 772, 1552, 6145, 17408, 17920, 77824, 360448, 3407872, 4194307, 5046273, 42729483, + 50331685, 50331721, 50331724, 61865997, 64487430, 67109009, 67109138, 69206033, 81264656, 84410391, 89391126, + 92274725, 92278805, 100696090, 101711899, 101810202, 109838362, 113246209, 113246229, 113247257, 113639449, + 117440574, 123732127, 146, 161, 296, 336, 392, 896, 3074, 18432, 35840, 155648, 720896, 6815744, 9240578, + 12582947, 19660804, 33554697, 41418760, 50331853, 50348045, 50855948, 51052557, 61865998, 67108995, 67109015, + 67111955, 70123539, 84934679, 92274743, 100663451, 100664090, 109838361, 162, 259, 265, 1540, 4160, 8224, + 12289, 16400, 20480, 32776, 65540, 71680, 131074, 262145, 311296, 1441792, 13631499, 16777222, 24117249, + 25165824, 25165894, 25427974, 27262998, 45613067, 50331695, 54525996, 54919181, 58720287, 67109019, 67239955, + 83230737, 83886231, 92274737, 97189908, 100663370, 100663390, 100663442, 104857627, 109051992, 109314072, + 113246219, 128974908, 129007644, 266, 273, 536, 3104, 6146, 33792, 143360, 622592, 2883584, 4194309, 4620289, + 9830402, 12713987, 31981575, 32243715, 33554442, 36986889, 40632328, 41943049, 48234498, 49676298, 50331717, + 50331785, 50331788, 50332045, 50954253, 53215245, 67109137, 67109394, 67115027, 73924630, 79364113, 88080407, + 92282901, 96469020, 98041877, 100664858, 100728858, 101711896, 109576216, 113248281, 117440606, 123731987, + 123731990, 123731993, 123732255, 262, 274, 289, 400, 592, 672, 1792, 3076, 24577, 34816, 286720, 1245184, + 5767168, 8388614, 10403842, 12582979, 20709380, 20971525, 23068685, 33554953, 36700185, 36962315, 41943050, + 44826635, 46137370, 48234510, 50364429, 54657036, 67109043, 67109123, 69664787, 70254610, 73400370, 79167507, + 79691793, 92274740, 92274775, 92274805, 92700693, 96468996, 100663448, 100663579, 102432794, 104202266, + 113246264, 117964830, 132907037, 261, 276, 290, 321, 515, 1544, 8256, 12290, 16416, 32784, 36864, 65544, + 131076, 262146, 524289, 573440, 2490368, 4915201, 13631488, 13631507, 13737987, 24117255, 25165958, 27263014, + 33554432, 35127305, 44695563, 50331727, 50332429, 50855945, 50905101, 54526028, 54788108, 56623132, 58720303, + 61865995, 67109147, 67121171, 67371027, 69206039, 69632019, 73465874, 77594641, 78643221, 79167504, 83886097, + 83886359, 88473622, 92274769, 93126677, 100663434, 100663454, 100663570, 100666394, 109052056, 111149080, + 128974940, 129237020, 292, 322, 529, 784, 1072, 6148, 6208, 40960, 49153, 1146880, 4194313, 4980736, 6291459, + 20316164, 25165829, 27328518, 28311566, 29360134, 30932999, 33554444, 36962305, 50331648, 50331781, 50331916, + 54968332, 60227599, 67108884, 67109393, 67109906, 73924634, 75169810, 83886098, 85590038, 92274901, 92291093, + 92536855, 100794394, 109051931, 113246249, 113250329, 113377304, 117440670, 119537694, 123732511, 129499164, + 164, 324, 518, 530, 545, 1184, 1344, 3080, 3584, 24578, 67584, 2293760, 8388618, 10354690, 12583043, + 14155783, 14680067, 23068693, 27394054, 33554437, 33555465, 36700201, 36732937, 36962317, 37093384, 39845897, + 46137386, 50333197, 50397197, 55574540, 64487454, 67109171, 67109379, 67133459, 70254609, 73400402, 73924610, + 74186768, 83099664, 83230738, 83886100, 85458975, 92274772, 92536852, 92635157, 100663576, 100663835, + 100669466, 101711890, 102170650, 106430489, 106692634, 113246267, 113246296, 121634846, 123830303, 124518431, + 128974874, 517, 532, 16448, 69632, 524290, 1048577, 4587520, 27262976, 46137353, 50331658, 50331741, + 54525961, 56623148, 58720268, 58982415, 67109143, 67109203, 67633171, 78643225, 100663482, 102236187, + 106954779, 123731982 }; + +static int cbest_28[1023] = { + 1, 2, 134217732, 4, 67108866, 8, 33554433, 16, 32, 150994948, 64, 128, 75497474, 256, 512, 37748737, 1024, + 2048, 4096, 153092100, 8192, 16384, 32768, 76546050, 65536, 131072, 262144, 38273025, 524288, 1048576, + 2097152, 4194304, 153354244, 8388608, 16777216, 33554432, 76677122, 67108864, 3, 134217728, 134217733, 5, + 38338561, 67108867, 134217734, 6, 9, 18, 36, 72, 144, 288, 576, 1152, 2304, 4608, 9216, 18432, 36864, 73728, + 147456, 294912, 589824, 1179648, 2359296, 4718592, 9437184, 18874368, 37748736, 201326598, 10, 17, 33554435, + 67108870, 75497472, 134217740, 167772165, 12, 33, 33554437, 67108874, 100663299, 134217748, 150994944, + 150994949, 20, 34, 65, 33554441, 67108882, 134217764, 150994950, 24, 66, 129, 33554449, 67108898, 75497475, + 134217796, 153387012, 218103814, 40, 68, 130, 257, 33554465, 67108930, 134217860, 150994956, 184549381, + 209715206, 48, 132, 258, 513, 33554497, 67108994, 75497478, 134217988, 150994964, 80, 136, 260, 514, 1025, + 33554561, 37748739, 67109122, 75497482, 109051907, 134218244, 150994980, 171966469, 96, 264, 516, 1026, 2049, + 33554689, 37748741, 67109378, 75497490, 104857603, 134218756, 150995012, 160, 272, 520, 1028, 2050, 4097, + 33554945, 37748745, 38273024, 67109890, 75497506, 76546048, 76693506, 134219780, 150995076, 153092096, + 153092101, 226492422, 192, 528, 1032, 2052, 4098, 8193, 19136512, 33555457, 37748753, 67110914, 75497538, + 134221828, 150995204, 153092102, 320, 544, 1040, 2056, 4100, 8194, 16385, 9568256, 33556481, 37748769, + 67112962, 75497602, 134225924, 150995460, 188743685, 220200966, 384, 1056, 2064, 4104, 8196, 16386, 32769, + 4784128, 33558529, 37748801, 67117058, 75497730, 76546051, 134234116, 150995972, 153092108, 186646533, 640, + 1088, 2080, 4112, 8200, 16388, 32770, 65537, 2392064, 33562625, 37748865, 67125250, 75497986, 113246211, + 134250500, 150996996, 153092116, 210763782, 768, 2112, 4128, 8208, 16392, 32772, 65538, 131073, 1196032, + 33570817, 37748993, 38346753, 67141634, 75498498, 76546054, 134283268, 150999044, 153092132, 1280, 2176, + 4160, 8224, 16400, 32776, 65540, 131074, 262145, 598016, 33587201, 37749249, 67174402, 75499522, 76546058, + 110100483, 134348804, 151003140, 153092164, 1536, 4224, 8256, 16416, 32784, 65544, 131076, 262146, 299008, + 524289, 33619969, 37749761, 38273027, 67239938, 75501570, 76546066, 134479876, 151011332, 153092228, + 172490757, 228589574, 2560, 4352, 8320, 16448, 32800, 65552, 131080, 149504, 262148, 524290, 1048577, + 33685505, 37750785, 38273029, 67371010, 75505666, 76546082, 105381891, 134742020, 151027716, 153092356, + 227540998, 3072, 8448, 16512, 32832, 65568, 74752, 131088, 262152, 524292, 1048578, 2097153, 33816577, + 37752833, 38273033, 67633154, 75513858, 76546114, 135266308, 151060484, 153092612, 190840837, 5120, 8704, + 16640, 32896, 37376, 65600, 131104, 262160, 524296, 1048580, 2097154, 4194305, 34078721, 37756929, 38273041, + 68157442, 75530242, 76546178, 136314884, 151126020, 153093124, 153354240, 153354245, 6144, 16896, 18688, + 33024, 65664, 131136, 262176, 524304, 1048584, 2097156, 4194306, 8388609, 34603009, 37765121, 38273057, + 69206018, 75563010, 76546306, 76677120, 138412036, 151257092, 153094148, 153354246, 153391108, 189267973, + 9344, 10240, 17408, 33280, 65792, 131200, 262208, 524320, 1048592, 2097160, 4194308, 8388610, 16777217, + 35651585, 37781505, 38273089, 38338560, 71303170, 75628546, 76546562, 114294787, 142606340, 151519236, + 153096196, 220463110, 4672, 12288, 33792, 66048, 131328, 262272, 524352, 1048608, 2097168, 4194312, 8388612, + 16777218, 37814273, 38273153, 75759618, 76547074, 113770499, 152043524, 153100292, 153354252, 186908677, + 2336, 20480, 34816, 66560, 131584, 262400, 524416, 1048640, 2097184, 4194320, 8388616, 16777220, 19169280, + 33554434, 37879809, 38273281, 41943041, 76021762, 76548098, 76677123, 83886082, 153108484, 153354260, + 167772164, 1168, 24576, 67584, 132096, 262656, 524544, 1048704, 2097216, 4194336, 8388624, 16777224, + 33554436, 38010881, 38273537, 50331649, 67108865, 76550146, 100663298, 153124868, 153354276, 155189252, + 210894854, 229638150, 584, 40960, 69632, 133120, 263168, 524800, 1048832, 2097280, 4194368, 8388640, 9584640, + 16777232, 33554440, 38274049, 76554242, 76677126, 77594626, 153157636, 153354308, 159383556, 201326596, 292, + 49152, 135168, 264192, 525312, 1049088, 2097408, 4194432, 8388672, 16777248, 33554448, 38275073, 38797313, + 67108868, 67108880, 76562434, 76677130, 76695554, 79691778, 110231555, 134217729, 153223172, 153354372, + 228851718, 146, 81920, 139264, 266240, 526336, 1049600, 2097664, 4194560, 4792320, 8388736, 16777280, + 33554464, 38277121, 39845889, 67108872, 76578818, 76677138, 100663297, 134217730, 134217735, 134217760, + 153354500, 184549380, 191365125, 7, 19, 37, 73, 145, 289, 577, 1153, 2305, 4609, 9217, 18433, 36865, 73729, + 98304, 147457, 270336, 294913, 528384, 589825, 1050624, 1179649, 2098176, 2359297, 4194816, 4718593, 8388864, + 9437185, 16777344, 18874369, 33554496, 38281217, 38338563, 76611586, 76677154, 92274690, 153354756, + 153616388, 172556293, 191102981, 201326594, 201326599, 227672070, 11, 38, 74, 290, 578, 1154, 2306, 4610, + 9218, 18434, 36866, 73730, 147458, 163840, 278528, 294914, 532480, 589826, 1052672, 1179650, 2099200, + 2359298, 2396160, 4195328, 4718594, 8389120, 9437186, 16777472, 18874370, 33554560, 37748738, 38289409, + 38338565, 46137345, 67108871, 67108896, 75497473, 76677186, 105447427, 109051906, 134217736, 134217741, + 134217750, 134217804, 134217876, 134218020, 134218308, 134218884, 134220036, 134222340, 134226948, 134236164, + 134254596, 134291460, 134365188, 134512644, 134807556, 135397380, 136577028, 138936324, 143654916, 153355268, + 154140676, 167772161, 171966468, 218103812, 13, 22, 76, 148, 580, 1156, 2308, 4612, 9220, 18436, 36868, + 73732, 147460, 196608, 294916, 540672, 589828, 1056768, 1179652, 2101248, 2359300, 4196352, 4718596, 8389632, + 9437188, 16777728, 18874372, 33554688, 37748740, 38305793, 38338569, 54525953, 67108875, 67108902, 67108928, + 67108938, 67109010, 67109154, 67109442, 67110018, 67111170, 67113474, 67118082, 67127298, 67145730, 67182594, + 67256322, 67403778, 67698690, 68288514, 69468162, 71827458, 76677250, 76808194, 85983234, 104857602, + 114819075, 134217742, 134217744, 134217749, 150994945, 153356292, 167772167, 209715204, 14, 21, 26, 35, 44, + 152, 296, 1160, 2312, 4616, 9224, 18440, 36872, 73736, 147464, 294920, 327680, 557056, 589832, 1064960, + 1179656, 1198080, 2105344, 2359304, 4198400, 4718600, 8390656, 9437192, 16778240, 18874376, 33554439, + 33554451, 33554469, 33554505, 33554577, 33554721, 33554944, 33555009, 33555585, 33556737, 33559041, 33563649, + 33572865, 33591297, 33628161, 33701889, 33849345, 34144257, 34734081, 35913729, 37748744, 38338577, 42991617, + 52428801, 67108883, 67108992, 75497476, 75497488, 76677378, 77070338, 134217765, 150994946, 150994951, + 150994976, 153358340, 157286404, 201326606, 234881031, 25, 52, 67, 88, 304, 592, 2320, 4624, 9232, 18448, + 36880, 73744, 147472, 294928, 393216, 589840, 1081344, 1179664, 2113536, 2359312, 4202496, 4718608, 8392704, + 9437200, 16779264, 18874384, 33554443, 33555456, 37748752, 38338593, 38347777, 38404097, 67108878, 67108899, + 67109120, 75497480, 76677634, 100663303, 109051905, 114425859, 134217766, 134217792, 134217797, 153362436, + 153387008, 153387013, 161480708, 167772173, 189333509, 201326614, 218103810, 218103815, 41, 50, 69, 104, 131, + 176, 608, 1184, 4640, 9248, 18464, 36896, 73760, 147488, 294944, 589856, 599040, 655360, 1114112, 1179680, + 2129920, 2359328, 4210688, 4718624, 8396800, 9437216, 16781312, 18874400, 33554445, 33556480, 37748768, + 38338625, 38535169, 67108886, 67108931, 67109376, 76678146, 78643202, 100663307, 104857601, 134217756, + 134217798, 134217856, 134217861, 150994952, 150994957, 150994966, 150995020, 150995092, 150995236, 150995524, + 150996100, 150997252, 150999556, 151004164, 151013380, 151031812, 151068676, 151142404, 151289860, 151584772, + 152174596, 153370628, 153387014, 155713540, 160432132, 167772181, 184549377, 188743684, 201326630, 209715202, + 209715207, 28, 42, 49, 70, 82, 100, 133, 208, 259, 352, 1216, 2368, 9280, 18496, 36928, 73792, 147520, + 294976, 589888, 786432, 1179712, 2162688, 2359360, 4227072, 4718656, 8404992, 9437248, 16785408, 18874432, + 33554453, 33554467, 33558528, 37748800, 38338689, 67108890, 67108995, 67109888, 75497479, 75497504, 76679170, + 76693504, 80740354, 100663315, 113836035, 134217772, 134217862, 134217984, 134217989, 150994958, 150994960, + 150994965, 167772197, 184549383, 186646532, 201326662, 220495878, 226492420, 229900294, 81, 134, 137, 164, + 200, 261, 416, 515, 704, 4736, 36992, 73856, 147584, 295040, 299520, 1179776, 2228224, 2359424, 8421376, + 9437312, 18874496, 33554457, 33554499, 33562624, 37748864, 67108906, 67108934, 67109123, 67110912, 75497483, + 75497510, 75497536, 75497546, 75497762, 75498050, 75499778, 75502082, 75506690, 75515906, 75534338, 75571202, + 75644930, 75792386, 76087298, 76681218, 77856770, 80216066, 94371842, 100663331, 113246210, 134217780, + 134217990, 134218240, 150994981, 153419780, 167772229, 171966465, 201326726, 218103822, 229769222, 251658247 }; + +static int cbest_29[1023] = { + 1, 2, 268435458, 4, 134217729, 8, 16, 335544322, 32, 64, 167772161, 128, 256, 512, 352321538, 1024, 2048, + 4096, 176160769, 8192, 16384, 32768, 65536, 356515842, 131072, 262144, 524288, 1048576, 178257921, 2097152, + 4194304, 8388608, 16777216, 33554432, 357564418, 67108864, 134217728, 268435456, 3, 178782209, 268435459, 5, + 10, 20, 40, 80, 160, 320, 640, 1280, 2560, 5120, 10240, 20480, 40960, 81920, 163840, 327680, 655360, 1310720, + 2621440, 5242880, 10485760, 20971520, 41943040, 83886080, 167772160, 6, 9, 134217731, 268435462, 335544320, + 402653187, 17, 134217733, 268435466, 335544323, 12, 18, 33, 134217737, 268435474, 34, 65, 134217745, + 268435490, 335544326, 469762051, 24, 36, 66, 129, 134217761, 167772163, 268435522, 335544330, 357826562, + 436207619, 68, 130, 257, 134217793, 167772165, 176160768, 268435586, 335544338, 352321536, 48, 72, 132, 258, + 513, 88080384, 134217857, 167772169, 268435714, 335544354, 352321539, 136, 260, 514, 1025, 44040192, + 134217985, 167772177, 268435970, 335544386, 503316483, 96, 144, 264, 516, 1026, 2049, 22020096, 134218241, + 167772193, 268436482, 335544450, 352321542, 486539267, 272, 520, 1028, 2050, 4097, 11010048, 134218753, + 167772225, 268437506, 335544578, 352321546, 192, 288, 528, 1032, 2052, 4098, 8193, 5505024, 134219777, + 167772289, 176160771, 178913281, 268439554, 335544834, 352321554, 444596227, 544, 1040, 2056, 4100, 8194, + 16385, 2752512, 134221825, 167772417, 176160773, 268443650, 335545346, 352321570, 384, 576, 1056, 2064, 4104, + 8196, 16386, 32769, 1376256, 134225921, 167772673, 176160777, 268451842, 335546370, 352321602, 356515840, + 520093699, 1088, 2080, 4112, 8200, 16388, 32770, 65537, 688128, 134234113, 167773185, 176160785, 178257920, + 268468226, 335548418, 352321666, 356515843, 511705091, 768, 1152, 2112, 4128, 8208, 16392, 32772, 65538, + 131073, 344064, 134250497, 167774209, 176160801, 268500994, 335552514, 352321794, 2176, 4160, 8224, 16400, + 32776, 65540, 131074, 172032, 262145, 89128960, 134283265, 167776257, 176160833, 268566530, 335560706, + 352322050, 356515846, 490733571, 1536, 2304, 4224, 8256, 16416, 32784, 65544, 86016, 131076, 262146, 524289, + 134348801, 167780353, 176160897, 268697602, 335577090, 352322562, 356515850, 4352, 8320, 16448, 32800, 43008, + 65552, 131080, 262148, 524290, 1048577, 44564480, 134479873, 167788545, 176161025, 268959746, 335609858, + 352323586, 356515858, 357892098, 3072, 4608, 8448, 16512, 21504, 32832, 65568, 131088, 262152, 524292, + 1048578, 2097153, 134742017, 167804929, 176161281, 178257923, 269484034, 335675394, 352325634, 356515874, + 446693379, 528482307, 8704, 10752, 16640, 32896, 65600, 131104, 262160, 524296, 1048580, 2097154, 4194305, + 22282240, 135266305, 167837697, 176161793, 178257925, 270532610, 335806466, 352329730, 356515906, 524288003, + 5376, 6144, 9216, 16896, 33024, 65664, 131136, 262176, 524304, 1048584, 2097156, 4194306, 8388609, 136314881, + 167903233, 176162817, 178257929, 272629762, 336068610, 352337922, 356515970, 2688, 17408, 33280, 65792, + 131200, 262208, 524320, 1048592, 2097160, 4194308, 8388610, 11141120, 16777217, 138412033, 168034305, + 176164865, 178257937, 276824066, 336592898, 352354306, 356516098, 357564416, 513802243, 1344, 12288, 18432, + 33792, 66048, 131328, 262272, 524352, 1048608, 2097168, 4194312, 8388612, 16777218, 33554433, 142606337, + 168296449, 176168961, 178257953, 285212674, 337641474, 352387074, 356516354, 357564419, 672, 34816, 66560, + 131584, 262400, 524416, 1048640, 2097184, 4194320, 5570560, 8388616, 16777220, 33554434, 67108865, 150994945, + 168820737, 176177153, 178257985, 178782208, 301989890, 339738626, 352452610, 356516866, 336, 24576, 36864, + 67584, 132096, 262656, 524544, 1048704, 2097216, 4194336, 8388624, 16777224, 33554436, 67108866, 169869313, + 176193537, 178258049, 178946049, 343932930, 352583682, 356517890, 357564422, 491782147, 168, 69632, 133120, + 263168, 524800, 1048832, 2097280, 2785280, 4194368, 8388640, 16777232, 33554440, 67108868, 134217730, + 171966465, 176226305, 178258177, 201326593, 352845826, 356519938, 357564426, 402653186, 532676611, 84, 49152, + 73728, 135168, 264192, 525312, 1049088, 2097408, 4194432, 8388672, 16777248, 33554448, 67108872, 89391104, + 134217732, 176291841, 178258433, 268435457, 353370114, 356524034, 357564434, 369098754, 530579459, 42, + 139264, 266240, 526336, 1049600, 1392640, 2097664, 4194560, 8388736, 16777280, 33554464, 67108880, 134217736, + 176422913, 178258945, 184549377, 268435464, 354418690, 356532226, 357564450, 11, 21, 41, 81, 161, 321, 641, + 1281, 2561, 5121, 10241, 20481, 40961, 81921, 98304, 147456, 163841, 270336, 327681, 528384, 655361, 1050624, + 1310721, 2098176, 2621441, 4194816, 5242881, 8388864, 10485761, 16777344, 20971521, 33554496, 41943041, + 67108896, 83886081, 134217744, 176685057, 178259969, 178782211, 268435460, 356548610, 357564482, 402653185, + 447217667, 469762050, 525336579, 7, 22, 82, 162, 322, 642, 1282, 2562, 5122, 10242, 20482, 40962, 81922, + 163842, 278528, 327682, 532480, 655362, 696320, 1052672, 1310722, 2099200, 2621442, 4195328, 5242882, + 8389120, 10485762, 16777472, 20971522, 33554560, 41943042, 44695552, 67108928, 83886082, 134217760, + 167772162, 177209345, 178262017, 178782213, 234881025, 268435463, 268435478, 268435498, 268435538, 268435618, + 268435778, 268436098, 268436738, 268438018, 268440578, 268445698, 268455938, 268476418, 268517378, 268599298, + 268763138, 269090818, 269746178, 271056898, 273678338, 278921218, 289406978, 310378498, 335544321, 356581378, + 357564546, 360710146, 436207618, 14, 44, 164, 324, 644, 1284, 2564, 5124, 10244, 20484, 40964, 81924, 163844, + 196608, 294912, 327684, 540672, 655364, 1056768, 1310724, 2101248, 2621444, 4196352, 5242884, 8389632, + 10485764, 16777728, 20971524, 33554688, 41943044, 67108992, 83886084, 134217739, 134217749, 134217769, + 134217792, 134217809, 134217889, 134218049, 134218369, 134219009, 134220289, 134222849, 134227969, 134238209, + 134258689, 134299649, 134381569, 134545409, 134873089, 135528449, 136839169, 139460609, 144703489, 155189249, + 167772164, 178266113, 178782217, 218103809, 268435467, 268435472, 335544328, 356646914, 357564674, 13, 19, + 28, 88, 328, 648, 1288, 2568, 5128, 10248, 20488, 40968, 81928, 163848, 327688, 348160, 557056, 655368, + 1064960, 1310728, 2105344, 2621448, 4198400, 5242888, 8390656, 10485768, 16778240, 20971528, 33554944, + 41943048, 67109120, 83886088, 134217735, 134217856, 167772168, 178274305, 178782225, 180355073, 268435475, + 268435488, 335544324, 356777986, 357564930, 385875970, 402653191, 469762049, 514326531, 26, 35, 56, 176, 656, + 1296, 2576, 5136, 10256, 20496, 40976, 81936, 163856, 327696, 393216, 589824, 655376, 1081344, 1310736, + 2113536, 2621456, 4202496, 5242896, 8392704, 10485776, 16779264, 20971536, 22347776, 33555456, 41943056, + 67109376, 83886096, 134217984, 167772176, 178290689, 178782241, 268435470, 268435491, 268435520, 335544327, + 335544342, 335544362, 335544402, 335544482, 335544642, 335544962, 335545602, 335546882, 335549442, 335554562, + 335564802, 335585282, 335626242, 335708162, 335872002, 336199682, 336855042, 338165762, 340787202, 346030082, + 357040130, 357565442, 357826560, 357908482, 377487362, 402653195, 436207617, 503316482, 25, 37, 52, 67, 112, + 352, 1312, 2592, 5152, 10272, 20512, 40992, 81952, 163872, 174080, 327712, 655392, 1114112, 1310752, 2129920, + 2621472, 4210688, 5242912, 8396800, 10485792, 16781312, 20971552, 33556480, 41943072, 67109888, 83886112, + 134217741, 134217747, 134218240, 167772192, 178323457, 178782273, 192937985, 268435523, 268435584, 335544331, + 335544336, 357566466, 357826563, 402653203, 486539266, 534773763, 38, 69, 74, 104, 131, 224, 704, 2624, 5184, + 10304, 20544, 41024, 81984, 163904, 327744, 655424, 786432, 1179648, 1310784, 2162688, 2621504, 4227072, + 5242944, 8404992, 10485824, 16785408, 20971584, 33558528, 41943104, 67110912, 83886144, 134217763, 134218752, + 167772171, 167772181, 167772201, 167772224, 167772241, 167772321, 167772481, 167772801, 167773441, 167774721, + 167777281, 167782401, 167792641, 167813121, 167854081, 167936001, 168099841, 168427521, 169082881, 170393601, + 173015041, 178388993, 178782337, 188743681, 251658241, 268435482, 268435494, 268435587, 268435712, 335544339, + 335544352, 352321537, 357568514, 358612994, 402653219, 469762055, 533725187, 49, 70, 73, 133, 138, 148, 208, + 259, 448, 1408, 5248, 10368, 20608, 41088, 82048, 87040, 163968, 327808, 655488, 1310848, 2228224, 2621568, + 4259840, 5243008, 8421376, 10485888, 11173888, 16793600, 20971648, 33562624, 41943168, 67112960, 83886208, + 88080385, 134217753, 134217765, 134217795, 134219776, 167772167, 167772288, 176160770, 178520065, 178782465, + 178913280, 243269633, 268435526, 268435715, 268435968, 335544334, 335544355, 335544384, 352321544, 357572610, + 357826566, 402653251, 436207623, 444596226, 469762059, 492044291, 503316481, 50, 134, 137, 261, 266, 296, + 416, 515, 896, 2816, 20736, 41216, 82176, 164096, 327936, 655616, 1310976, 1572864, 2359296, 2621696, + 8454144, 10486016, 16809984, 20971776, 33570816, 44040193, 67117056, 83886336, 134217797, 167772416, + 178782721, 268435506, 268435530, 268435590, 268435971, 268436480, 335544387, 335544448, 352321540, 357826570, + 364904450, 402653315, 436207627, 469762067, 486539265 }; + +static int cbest_30[1023] = { + 1, 2, 541065219, 4, 811597826, 8, 405798913, 16, 32, 64, 743964675, 128, 913047554, 256, 541065218, + 270532609, 3, 512, 456523777, 541065217, 6, 811597827, 5, 676331523, 12, 129, 405798912, 258, 811597824, 9, + 24, 516, 1024, 202899456, 541065223, 541065283, 10, 1032, 946864130, 48, 2064, 101449728, 879230978, 17, + 4128, 541065227, 811597858, 96, 8256, 50724864, 811597830, 20, 16512, 405798915, 18, 33, 192, 2048, 33024, + 25362432, 405798929, 473432065, 541065235, 769327107, 66048, 439615489, 743964674, 811597834, 132096, + 12681216, 405798917, 34, 40, 65, 264192, 541065251, 528384, 6340608, 743964673, 811597842, 384, 1056768, + 405798921, 36, 66, 4096, 2113536, 3170304, 371982337, 743964683, 80, 4227072, 1585152, 8454144, 777781251, + 68, 130, 768, 16908288, 541065347, 743964679, 760872963, 913047555, 792576, 33816576, 811597890, 917340162, + 160, 67633152, 405798945, 72, 132, 257, 8192, 396288, 135266304, 913047552, 1536, 270532608, 811597954, + 913047558, 260, 198144, 405798977, 727056387, 136, 456523776, 541065475, 743964691, 193, 386, 99072, 514, + 3072, 405799041, 541065216, 929955842, 144, 320, 513, 16384, 49536, 743964707, 921501698, 997588994, 264, + 520, 772, 541065315, 676331522, 811598082, 7, 24768, 270532611, 456523779, 458670081, 913047562, 385, 6144, + 228261888, 338165761, 541065221, 541065411, 541065731, 743964739, 811597825, 13, 1028, 1544, 12384, + 270532641, 541065222, 541065282, 676331521, 14, 259, 270532613, 270532673, 405799169, 541065346, 811597874, + 904593410, 913047570, 946864131, 25, 272, 517, 770, 1025, 1040, 6192, 202899457, 541065473, 743964803, + 879230979, 11, 26, 131, 640, 1026, 1033, 3088, 12288, 405798914, 456523781, 541065226, 541065231, 541065281, + 676331539, 811597828, 811597859, 811597922, 811598338, 28, 49, 528, 2065, 3096, 101449729, 270532617, + 405798928, 464977921, 473432064, 541065225, 676331555, 710148099, 811597831, 913047586, 946864128, 161, 288, + 518, 1540, 2056, 4129, 32768, 114130944, 202899458, 202899464, 405798937, 439615488, 460750849, 498794497, + 541065243, 541065735, 541066243, 676331527, 811597955, 879230976, 22, 52, 97, 133, 1034, 1548, 6176, 8257, + 50724865, 101449732, 405798916, 456523785, 541065234, 541065299, 541066251, 769327106, 811597856, 811598080, + 21, 50, 56, 262, 322, 2066, 2080, 16513, 24576, 50724866, 101449730, 236716032, 270532625, 405798961, + 405799040, 405799425, 541065267, 541067283, 642514947, 811597835, 811597838, 879230986, 913047618, 946864146, + 1014497282, 19, 774, 2049, 3080, 4130, 33025, 25362433, 202899460, 202899520, 219807744, 541065287, + 541069347, 676331531, 743964931, 811597832, 811597866, 879230994, 980680706, 44, 98, 104, 137, 644, 1036, + 8258, 12352, 66049, 101449760, 405798919, 405798920, 456523793, 541065233, 541065250, 541073475, 591790083, + 769327105, 811597850, 811598342, 811598850, 946864134, 946864194, 112, 266, 387, 2052, 2068, 4112, 16514, + 132097, 12681217, 50724880, 118358016, 371982336, 405798933, 452296705, 541065239, 541081731, 743964672, + 811597843, 811598858, 879230982, 896139266, 913047682, 35, 41, 194, 524, 544, 1056, 1280, 2050, 4132, 6160, + 33026, 264193, 25362434, 25362440, 57065472, 109903872, 405798925, 405798931, 405800961, 439615493, + 473432067, 473432073, 541065291, 541067267, 541073411, 541098243, 545357827, 566427651, 770400259, 811597862, + 811599890, 811601922, 42, 88, 100, 145, 208, 4160, 8260, 16385, 24704, 66050, 528385, 6340609, 12681220, + 50724868, 405799171, 439615491, 439615497, 456523809, 541065249, 541131267, 743964682, 743964687, 811601954, + 946864138, 38, 224, 274, 2072, 16516, 132098, 1056769, 6340610, 12681218, 59179008, 101449736, 185991168, + 405799429, 405799937, 473432097, 507248641, 539017219, 541065410, 541197315, 743964681, 805355522, 811597840, + 811606082, 862322690, 37, 67, 196, 532, 576, 1288, 4097, 4136, 12320, 33028, 49152, 65536, 264194, 2113537, + 3170305, 25362436, 54951936, 202899472, 405798923, 405799945, 473432069, 490340353, 541065259, 541329411, + 743964677, 743964699, 743965187, 743965699, 765165571, 769327111, 777781250, 811597846, 811614338, 81, 176, + 388, 1048, 8224, 8264, 49408, 66052, 528386, 4227073, 50724872, 384663553, 402677761, 405798944, 405800977, + 456523841, 541593603, 743964678, 760872962, 782073859, 811598018, 811599874, 811630850, 815890434, 836960258, + 70, 290, 16520, 32770, 132100, 1056770, 1585153, 4227074, 8454145, 29589504, 92995584, 101449744, 270532705, + 270532737, 371982341, 405803041, 448069633, 536903683, 541065603, 542121987, 743964802, 760872961, 811597891, + 811597986, 811663874, 913047810, 917340163, 69, 84, 200, 548, 769, 4098, 4104, 4144, 8320, 24640, 33032, + 264196, 2113538, 3170306, 8454146, 16908289, 27475968, 28532736, 202899488, 371982339, 405799009, 405807169, + 541065255, 541065539, 541069315, 543178755, 544235523, 676331587, 743964929, 769327115, 771440643, 777781249, + 809517058, 810573826, 811729922, 76, 82, 416, 1064, 2112, 8272, 66056, 528388, 792577, 6340612, 8454148, + 16908290, 33816577, 404758529, 405798976, 405798993, 405815425, 456523905, 541065345, 777781255, 811862018, + 913047553, 913047556, 913048066, 946864162, 134, 448, 641, 2096, 2560, 2576, 16528, 132104, 1056772, 1585154, + 12681224, 14794752, 16908292, 46497792, 67633153, 405799105, 405831937, 407945217, 431161345, 542650371, + 549519363, 760872967, 811597888, 812126210, 879231010, 913047559, 917340160, 73, 392, 580, 776, 1088, 4100, + 8193, 16448, 33040, 65540, 98304, 264200, 396289, 2113540, 3170308, 13737984, 16908296, 25362448, 33816580, + 135266305, 371982401, 388890625, 405864961, 473432081, 541065987, 557973507, 676331651, 727056386, 742404099, + 743965191, 758824963, 769327123, 777781267, 807436290, 811598210, 812654594, 74, 140, 352, 1096, 1537, 8288, + 66064, 98816, 528392, 792578, 4227076, 6340616, 33816578, 33816584, 50724896, 380436481, 403718145, + 405286913, 405931009, 418480129, 439615505, 541065474, 541857795, 574881795, 727056385, 743964690, 743965707, + 162, 168, 261, 1538, 2128, 16544, 132112, 198145, 1056776, 1585156, 7397376, 12681232, 23248896, 33816592, + 67633154, 67633160, 101449792, 270532865, 405798947, 405798953, 406063105, 456524033, 541065379, 608698371, + 676331571, 743444483, 743964723, 743966739, 794689539, 811597906, 811597952, 879231042, 913047566, 152, 832, + 1152, 4192, 8194, 24577, 33056, 49280, 131072, 264208, 396290, 2113544, 3170312, 6868992, 14266368, 25362464, + 67633168, 135266306, 202899584, 371982345, 406327297, 541065351, 541461507, 743964715, 743968803, 756711427, + 769327139, 786235395, 813182978, 820051970, 915259394, 917876738, 929955843, 138, 896, 1160, 1282, 5152, + 8208, 66080, 99073, 131080, 528400, 792580, 4227080, 6340624, 50724928, 67633184, 135266320, 270532610, + 405799297, 439615521, 456523778, 458670080, 541066755, 541077507, 743964689, 743964706, 743964771, 743972931, + 811597894, 811598594, 828506114, 913047683, 917340166, 921501699, 923713538, 929955840, 946864258, 997588995, + 164, 268, 400, 515, 645, 784, 1290, 1552, 2192, 2580, 3073, 4224, 5160, 10320, 16576, 16640, 20640, 41280, + 49154, 82560, 132128, 165120, 198146, 330240, 660480, 1056784, 1320960, 1585160, 2641920, 3698688, 5283840, + 8454152, 10567680, 11624448, 12681248, 21135360, 42270720, 67633156, 84541440, 101449856, 135266336, + 169082880, 338165760, 405798949, 405798979, 405803009, 541065314, 541065479, 541065601, 541263363, 725008387, + 742924291, 743964695, 743981187, 777781259, 811598083, 812390402, 845414402, 879231106, 913047808, 921501696, + 991346690, 997588992, 321, 3074, 4256, 8196, 33088, 49537, 196608, 264224, 396292, 2113552, 3170320, 3434496, + 25362496, 135266308, 135266368, 270532640, 270532657, 363528193, 371982353, 410025985, 473432129, 541065355, + 541065537, 541065729, 676331779, 743964867, 743966723, 743997699, 745037827, 748257283, 760872971, 769327171, + 811603970, 912267266, 913047563, 195, 265, 280, 521, 704, 773, 3076, 5120, 8384, 66112, 99074, 197632, + 528416, 792584, 4227088, 6340640, 50724992, 270532612, 270532672, 405799168, 414253057, 439615553, 541065220, + 541065730, 541164291, 727056419, 743964705, 743964738, 744030723, 811597898, 811597958, 811606018, 811994114, + 912787458, 913047560, 917340170, 148, 209, 324, 522, 1664, 24769, 32896, 132160, 198148, 262160, 1056800, + 1585168, 1849344, 5812224, 8454160, 12681280, 270532736, 270532801, 270533121, 405798981, 405799043, + 405799681, 405801985, 422707201, 541065313, 541068291, 541089795, 676331520, 722894851, 727056391, 741916675, + 743708675, 744096771, 811599362, 913047578, 913048070, 913048578, 918396930, 929955850, 146, 225, 418, 1546, + 2176, 2564, 6145, 8200, 10304, 16386, 33152, 49538, 98560, 264256, 396296, 1717248, 2113568, 3170336, + 7133184, 16908304, 25362560, 135266312, 202899712, 228261889, 371982369, 405799057, 406591489, 456523780, + 473432193, 541065363, 541081603, 541114755, 735510531, 744228867, 760872979, 769327235, 811597875, 811598019, + 811598086, 811598208, 811795970, 879231002, 904593411, 913047571, 913047574, 913048586, 197, 336, 1029, 1545, + 1568, 1792, 12385, 49153, 66176, 98308, 99076, 792592, 4227104, 270532615, 270532616, 456524289, 464977920, + 541065409, 541065472, 541065602, 541065991, 676331547, 743964737, 811597962, 811597987, 811598336, 811610114, + 912527362, 913049618, 917340178, 946864386 }; + +static int cbest_31[1023] = { + 1, 2, 1073741828, 4, 536870914, 8, 268435457, 16, 32, 1207959556, 64, 128, 603979778, 256, 512, 301989889, + 1024, 2048, 4096, 1224736772, 8192, 16384, 32768, 612368386, 65536, 131072, 262144, 306184193, 524288, + 1048576, 2097152, 4194304, 1226833924, 8388608, 16777216, 33554432, 67108864, 613416962, 134217728, + 268435456, 306708481, 536870912, 3, 1073741824, 1073741829, 5, 536870915, 1073741830, 6, 9, 18, 36, 72, 144, + 288, 576, 1152, 2304, 4608, 9216, 18432, 36864, 73728, 147456, 294912, 589824, 1179648, 2359296, 4718592, + 9437184, 18874368, 37748736, 75497472, 150994944, 301989888, 1610612742, 10, 17, 268435459, 536870918, + 603979776, 1073741836, 1227096068, 1342177285, 12, 33, 268435461, 536870922, 805306371, 1073741844, + 1207959552, 1207959557, 20, 34, 65, 268435465, 536870930, 1073741860, 1207959558, 24, 66, 129, 268435473, + 536870946, 603979779, 1073741892, 1744830470, 40, 68, 130, 257, 268435489, 536870978, 1073741956, 1207959564, + 1476395013, 1677721606, 48, 132, 258, 513, 268435521, 536871042, 603979782, 613548034, 1073742084, + 1207959572, 80, 136, 260, 514, 1025, 268435585, 301989891, 536871170, 603979786, 872415235, 1073742340, + 1207959588, 1375731717, 96, 264, 516, 1026, 2049, 268435713, 301989893, 536871426, 603979794, 838860803, + 1073742852, 1207959620, 160, 272, 520, 1028, 2050, 4097, 268435969, 301989897, 306184192, 536871938, + 603979810, 612368384, 1073743876, 1207959684, 1224736768, 1224736773, 1811939334, 192, 528, 1032, 2052, 4098, + 8193, 153092096, 268436481, 301989905, 536872962, 603979842, 1073745924, 1207959812, 1224736774, 320, 544, + 1040, 2056, 4100, 8194, 16385, 76546048, 268437505, 301989921, 306774017, 536875010, 603979906, 1073750020, + 1207960068, 1509949445, 1761607686, 384, 1056, 2064, 4104, 8196, 16386, 32769, 38273024, 268439553, + 301989953, 536879106, 603980034, 612368387, 1073758212, 1207960580, 1224736780, 1493172229, 640, 1088, 2080, + 4112, 8200, 16388, 32770, 65537, 19136512, 268443649, 301990017, 536887298, 603980290, 905969667, 1073774596, + 1207961604, 1224736788, 1686110214, 768, 2112, 4128, 8208, 16392, 32772, 65538, 131073, 9568256, 268451841, + 301990145, 536903682, 603980802, 612368390, 1073807364, 1207963652, 1224736804, 1280, 2176, 4160, 8224, + 16400, 32776, 65540, 131074, 262145, 4784128, 268468225, 301990401, 536936450, 603981826, 612368394, + 880803843, 1073872900, 1207967748, 1224736836, 1536, 4224, 8256, 16416, 32784, 65544, 131076, 262146, 524289, + 2392064, 268500993, 301990913, 306184195, 537001986, 603983874, 612368402, 1074003972, 1207975940, + 1224736900, 1379926021, 1828716550, 2560, 4352, 8320, 16448, 32800, 65552, 131080, 262148, 524290, 1048577, + 1196032, 268566529, 301991937, 306184197, 537133058, 603987970, 612368418, 843055107, 1074266116, 1207992324, + 1224737028, 1227128836, 1820327942, 3072, 8448, 16512, 32832, 65568, 131088, 262152, 524292, 598016, 1048578, + 2097153, 268697601, 301993985, 306184201, 537395202, 603996162, 612368450, 1074790404, 1208025092, + 1224737284, 1526726661, 5120, 8704, 16640, 32896, 65600, 131104, 262160, 299008, 524296, 1048580, 2097154, + 4194305, 268959745, 301998081, 306184209, 537919490, 604012546, 612368514, 1075838980, 1208090628, + 1224737796, 1226833920, 1226833925, 6144, 16896, 33024, 65664, 131136, 149504, 262176, 524304, 1048584, + 2097156, 4194306, 8388609, 269484033, 302006273, 306184225, 538968066, 604045314, 612368642, 613416960, + 1077936132, 1208221700, 1224738820, 1226833926, 1514143749, 10240, 17408, 33280, 65792, 74752, 131200, + 262208, 524320, 1048592, 2097160, 4194308, 8388610, 16777217, 270532609, 302022657, 306184257, 306708480, + 541065218, 604110850, 612368898, 914358275, 1082130436, 1208483844, 1224740868, 1763704838, 12288, 33792, + 37376, 66048, 131328, 262272, 524352, 1048608, 2097168, 4194312, 8388612, 16777218, 33554433, 272629761, + 302055425, 306184321, 545259522, 604241922, 612369410, 910163971, 1090519044, 1209008132, 1224744964, + 1226833932, 1495269381, 18688, 20480, 34816, 66560, 131584, 262400, 524416, 1048640, 2097184, 4194320, + 8388616, 16777220, 33554434, 67108865, 153354240, 276824065, 302120961, 306184449, 553648130, 604504066, + 612370434, 613416963, 613564418, 1107296260, 1210056708, 1224753156, 1226833940, 9344, 24576, 67584, 132096, + 262656, 524544, 1048704, 2097216, 4194336, 8388624, 16777224, 33554436, 67108866, 134217729, 285212673, + 302252033, 306184705, 570425346, 605028354, 612372482, 1140850692, 1212153860, 1224769540, 1226833956, + 1687158790, 1837105158, 4672, 40960, 69632, 133120, 263168, 524800, 1048832, 2097280, 4194368, 8388640, + 16777232, 33554440, 67108868, 76677120, 134217730, 302514177, 306185217, 606076930, 612376578, 613416966, + 1216348164, 1224802308, 1226833988, 2336, 49152, 135168, 264192, 525312, 1049088, 2097408, 4194432, 8388672, + 16777248, 33554448, 67108872, 134217732, 268435458, 303038465, 306186241, 335544321, 608174082, 612384770, + 613416970, 671088642, 881852419, 1224867844, 1226834052, 1342177284, 1830813702, 1168, 81920, 139264, 266240, + 526336, 1049600, 2097664, 4194560, 8388736, 16777280, 33554464, 38338560, 67108880, 134217736, 268435460, + 304087041, 306188289, 402653185, 536870913, 612401154, 613416978, 805306370, 1224998916, 1226834180, + 1241513988, 1530920965, 584, 98304, 270336, 528384, 1050624, 2098176, 4194816, 8388864, 16777344, 33554496, + 67108896, 134217744, 268435464, 306192385, 306708483, 612433922, 613416994, 620756994, 1225261060, + 1226834436, 1275068420, 1380450309, 1528823813, 1610612740, 1821376518, 292, 163840, 278528, 532480, 1052672, + 2099200, 4195328, 8389120, 16777472, 19169280, 33554560, 67108928, 134217760, 268435472, 306200577, + 306708485, 306782209, 310378497, 536870916, 536870928, 612499458, 613417026, 637534210, 843579395, + 1073741825, 1225785348, 1226834948, 146, 196608, 540672, 1056768, 2101248, 4196352, 8389632, 16777728, + 33554688, 67108992, 134217792, 268435488, 306216961, 306708489, 318767105, 536870920, 612630530, 613417090, + 805306369, 918552579, 1073741826, 1073741831, 1073741856, 1226835972, 1476395012, 7, 19, 37, 73, 145, 289, + 577, 1153, 2305, 4609, 9217, 18433, 36865, 73729, 147457, 294913, 327680, 557056, 589825, 1064960, 1179649, + 2105344, 2359297, 4198400, 4718593, 8390656, 9437185, 9584640, 16778240, 18874369, 33554944, 37748737, + 67109120, 75497473, 134217856, 150994945, 268435520, 306249729, 306708497, 612892674, 613417218, 738197506, + 1226838020, 1228931076, 1610612738, 1610612743, 11, 38, 74, 290, 578, 1154, 2306, 4610, 9218, 18434, 36866, + 73730, 147458, 294914, 393216, 589826, 1081344, 1179650, 2113536, 2359298, 4202496, 4718594, 8392704, + 9437186, 16779264, 18874370, 33555456, 37748738, 67109376, 75497474, 134217984, 150994946, 268435584, + 301989890, 306315265, 306708513, 369098753, 536870919, 536870944, 603979777, 613417474, 872415234, 915406851, + 1073741832, 1073741837, 1073741846, 1073741900, 1073741972, 1073742116, 1073742404, 1073742980, 1073744132, + 1073746436, 1073751044, 1073760260, 1073778692, 1073815556, 1073889284, 1074036740, 1074331652, 1074921476, + 1076101124, 1078460420, 1083179012, 1092616196, 1111490564, 1149239300, 1226842116, 1227096064, 1227096069, + 1233125380, 1342177281, 1375731716, 1514668037, 1744830468, 13, 22, 76, 148, 580, 1156, 2308, 4612, 9220, + 18436, 36868, 73732, 147460, 294916, 589828, 655360, 1114112, 1179652, 2129920, 2359300, 4210688, 4718596, + 4792320, 8396800, 9437188, 16781312, 18874372, 33556480, 37748740, 67109888, 75497476, 134218240, 150994948, + 268435712, 301989892, 306446337, 306708545, 436207617, 536870923, 536870950, 536870976, 536870986, 536871058, + 536871202, 536871490, 536872066, 536873218, 536875522, 536880130, 536889346, 536907778, 536944642, 537018370, + 537165826, 537460738, 538050562, 539230210, 541589506, 546308098, 555745282, 574619650, 613417986, 614465538, + 687865858, 838860802, 1073741838, 1073741840, 1073741845, 1207959553, 1226850308, 1227096070, 1342177287, + 1677721604, 14, 21, 26, 35, 44, 152, 296, 1160, 2312, 4616, 9224, 18440, 36872, 73736, 147464, 294920, + 589832, 786432, 1179656, 2162688, 2359304, 4227072, 4718600, 8404992, 9437192, 16785408, 18874376, 33558528, + 37748744, 67110912, 75497480, 134218752, 150994952, 268435463, 268435475, 268435493, 268435529, 268435601, + 268435745, 268435968, 268436033, 268436609, 268437761, 268440065, 268444673, 268453889, 268472321, 268509185, + 268582913, 268730369, 269025281, 269615105, 270794753, 273154049, 277872641, 287309825, 301989896, 306708609, + 343932929, 419430401, 536870931, 536871040, 603979780, 603979792, 613419010, 613548032, 616562690, 910688259, + 1073741861, 1207959554, 1207959559, 1207959584, 1226866692, 1258291204, 1610612750, 1763966982, 1839202310, + 1879048199, 25, 52, 67, 88, 304, 592, 2320, 4624, 9232, 18448, 36880, 73744, 147472, 294928, 589840, 1179664, + 1310720, 2228224, 2359312, 2396160, 4259840, 4718608, 8421376, 9437200, 16793600, 18874384, 33562624, + 37748752, 67112960, 75497488, 134219776, 150994960, 268435467, 268436480, 301989904, 306708737, 307232769, + 536870926, 536870947, 536871168, 603979784, 613421058, 805306375, 872415233, 1073741862, 1073741888, + 1073741893, 1226899460, 1227096076, 1291845636, 1342177293, 1495531525, 1610612758, 1744830466, 1744830471, + 1838153734, 41, 50, 69, 104, 131, 176, 608, 18464, 73760, 147488, 589856, 1179680, 1572864, 2359328, 4325376, + 4718624, 8454144, 9437216, 16809984, 18874400, 33570816, 67117056, 75497504, 134221824, 301989920, 306708993, + 306774016, 308281345, 536870934, 536870979, 629145602, 805306379, 1073741894, 1073741952, 1207959560, + 1207959700, 1207959844, 1207960708, 1207961860, 1207964164, 1207968772, 1207977988, 1207996420, 1208033284, + 1208107012, 1208549380, 1209139204, 1210318852, 1212678148, 1217396740, 1226964996, 1283457028, 1342177301, + 1476395009, 1509949444, 1610612774, 1677721607 }; + +static unsigned int cbest_32[1023] = { + 1, 2149580803, 2, 4, 3224371202, 8, 1612185601, 16, 32, 2955673603, 64, 128, 256, 3627417602, 512, 1024, + 2149580802, 1074790401, 1813708801, 3, 2149580801, 2048, 3224371203, 6, 2686976003, 5, 12, 1612185600, + 3224371200, 2149580807, 9, 24, 806092800, 3761766402, 10, 1025, 4096, 3493068802, 48, 2050, 403046400, + 2149580811, 2149581315, 17, 4100, 3056435203, 3224371206, 96, 8200, 201523200, 20, 16400, 1612185603, + 2149580819, 3224371458, 18, 33, 192, 32800, 100761600, 1880883201, 2955673602, 3224371210, 8192, 65600, + 1746534401, 384, 131200, 50380800, 1612185605, 2149580835, 34, 40, 65, 262400, 1612185729, 2955673601, + 3224371218, 768, 524800, 25190400, 1049600, 1612185609, 2149580867, 36, 66, 129, 1536, 2099200, 12595200, + 1477836801, 3224371234, 80, 16384, 4198400, 3090022403, 6297600, 8396800, 1612185617, 2149580931, 2955673607, + 2955673667, 3022848003, 3627417603, 68, 130, 257, 16793600, 3224371266, 3677798402, 3148800, 33587200, 160, + 3072, 67174400, 1612185633, 2149581059, 2955673611, 3627417600, 72, 132, 258, 513, 1574400, 134348800, + 3224371330, 32768, 268697600, 2888499203, 787200, 537395200, 1612185665, 2955673619, 136, 260, 320, 514, + 6144, 1074790400, 1813708800, 3627417634, 393600, 3627417606, 3694592002, 2149581827, 2955673635, 3661004802, + 3963289602, 144, 264, 516, 1026, 1537, 3074, 196800, 2149580800, 3224371714, 640, 12288, 65536, 3627417610, + 98400, 1612185857, 2149581571, 2686976002, 272, 520, 1028, 2049, 6148, 906854400, 3224372226, 7, 49200, + 1074790403, 1813708803, 1838899201, 2149580805, 2149582339, 3224371201, 3593830402, 3627417618, 1280, 2052, + 3073, 24576, 1343488001, 1612186113, 1813708817, 2149580806, 2149582851, 2686976001, 2955673731, 13, 288, + 528, 1032, 12296, 24600, 3224371586, 3761766403, 14, 131072, 1074790405, 1813708805, 3493068803, 25, 4098, + 6146, 12300, 806092801, 1612186625, 1847296001, 2149580810, 2149580815, 2149581314, 2955673859, 3224371204, + 3224371970, 11, 26, 544, 1040, 4097, 24592, 49152, 453427200, 1074790657, 1612185602, 1830502401, 1981644801, + 2149580809, 2149581826, 2821324803, 3056435202, 3224371207, 3224373250, 3761766400, 28, 49, 2051, 2056, 4104, + 6150, 403046401, 1074790409, 1074790913, 1813708809, 1880883200, 2149580827, 2149582849, 2686976007, + 3493068800, 3627417666, 4101, 12292, 806092802, 1612185793, 1746534400, 2149580818, 2149581313, 2149584899, + 2686976131, 2955674115, 3224371459, 22, 52, 97, 576, 1027, 1056, 2560, 3075, 8201, 49184, 201523201, + 1612185604, 2149580851, 2552627203, 2686976259, 3056435201, 3224371211, 3224371214, 4030464002, 21, 50, 56, + 8196, 16401, 98304, 262144, 403046402, 940441600, 1074790417, 1612185728, 1612185985, 2149584903, 2686976011, + 3224371208, 3224372227, 3627417730, 3896115202, 19, 193, 4102, 24584, 32801, 100761601, 806092804, 806092864, + 873267200, 1612187649, 1796915201, 2149580817, 2149580834, 2149580899, 2149582338, 2149589003, 2351104003, + 2955674627, 3056435211, 3224371226, 3224371456, 3224373248, 3761766406, 44, 98, 104, 1029, 1088, 2064, 8193, + 8202, 8208, 65601, 98368, 201523202, 226713600, 403046432, 1612185607, 1612185608, 2149580823, 2149597203, + 2955673600, 3224371219, 3224375298, 3493068806, 3493068866, 3560243202, 3761766530, 112, 385, 2054, 8194, + 16402, 131201, 50380801, 201523216, 403046404, 470220800, 1074790433, 1477836800, 1612186624, 1813708833, + 2149580995, 2149581319, 2149613603, 2250342403, 2686976019, 3224371250, 3493068930, 3627417858, 35, 41, 194, + 1281, 4112, 32802, 49168, 196608, 262401, 100761602, 100761608, 436633600, 806092808, 806093312, 1612185613, + 1880883203, 2149580833, 2149580866, 2149581443, 2149588995, 2149646403, 2955673699, 3056435207, 3224375302, + 3761766410, 3761766914, 42, 88, 100, 208, 769, 1033, 1152, 2080, 8204, 16392, 65602, 196736, 524801, + 25190401, 50380804, 201523204, 403046656, 1074791169, 1612185616, 1746534403, 2149581187, 2149712003, + 2199961603, 3069030403, 3224371216, 3224371235, 3224371298, 3224379402, 3425894402, 3493068810, 38, 224, 386, + 2058, 2562, 5120, 16404, 131202, 524288, 1049601, 25190402, 50380802, 201523328, 235110400, 403046408, + 738918400, 1074790465, 1528217601, 1612185625, 1813708865, 2015232001, 2149580843, 2149581323, 2149843203, + 2686976035, 2955673605, 2955673795, 3073228803, 3090022402, 3224371222, 3224371462, 3224371522, 3224387602, + 3627418114, 37, 67, 196, 4108, 16416, 32804, 98336, 262402, 2099201, 12595201, 100761604, 100761664, + 218316800, 806092816, 1612185611, 1612185731, 1612189697, 1746534433, 1880883205, 1880883265, 1948057601, + 2147485699, 2149580865, 2149580930, 2150105603, 2174771203, 2955673606, 2955673666, 2955675651, 3022848002, + 3064832003, 3140403203, 3224371394, 3224404002, 3325132802, 3761766418, 81, 176, 416, 770, 1041, 2112, 5124, + 16385, 65604, 393216, 393472, 524802, 2099202, 4198401, 50380832, 113356800, 201523208, 1612185632, + 1612185649, 1612187651, 1746534405, 1746534465, 2150630403, 3223323650, 3224371232, 3224371267, 3224379394, + 3224436802, 3493068818, 3677798403, 70, 388, 448, 2066, 16408, 131204, 1049602, 4198402, 6297601, 8396801, + 25190416, 117555200, 369459200, 403046416, 1074790529, 1612185761, 1612189701, 1780121601, 1813708929, + 1880883457, 2149580839, 2149581331, 2151684099, 2162176003, 2686976067, 3090022401, 3224371466, 3224502402, + 3274752002, 3627418626, 69, 84, 131, 200, 1538, 4116, 16388, 32784, 32808, 196672, 262404, 4198404, 8396802, + 12595202, 12595208, 16793601, 109158400, 806092832, 1477836803, 1611661825, 1612185697, 1612185733, + 1612193801, 1880883209, 2149580883, 2149580929, 2149581058, 2149597187, 2153779203, 2686976387, 2955673610, + 2955673615, 2955673665, 3022848001, 3056435219, 3224371242, 3224633602, 3627417601, 3761766434, 76, 82, 352, + 772, 832, 1057, 2176, 4128, 8216, 8224, 16386, 65608, 524804, 786944, 3148801, 6297604, 8396804, 25190404, + 33587201, 1612185621, 1612185664, 1612202001, 1746534409, 2148535299, 2157977603, 2955673609, 2955674626, + 3221228546, 3222276098, 3224371264, 3224371331, 3224896002, 3249561602, 3493068834, 3677798400, 134, 161, + 392, 896, 2082, 32832, 131208, 786432, 1048576, 1049604, 3148802, 6297602, 8396808, 16793604, 50380808, + 58777600, 67174401, 184729600, 1477836833, 1612185619, 1612218401, 1712947201, 1813709057, 2149580871, + 2149581347, 2166374403, 2888499202, 2955673627, 2955675649, 3048038403, 3224371474, 3627417650, 3677798406, + 73, 133, 259, 1540, 4132, 10248, 32816, 262408, 393344, 1574401, 2099204, 12595204, 16793602, 16793608, + 54579200, 100761616, 134348801, 1477836805, 1545011201, 1611138049, 1612185737, 1612193793, 1612251201, + 1880883217, 2149581057, 2183168003, 2955411715, 2955673618, 2955673683, 2955677699, 3022848019, 3056435235, + 3090022435, 3224371238, 3224372738, 3226474498, 3236966402, 3761766466, 74, 140, 704, 776, 1089, 1664, 2304, + 3076, 4160, 8232, 10240, 32769, 65616, 524808, 1573888, 16793616, 25190408, 33587202, 33587208, 56678400, + 201523232, 268697601, 1511424001, 1610614273, 1612316801, 1662566401, 1746534417, 2149580963, 2149583875, + 2216755203, 2955673651, 3022848035, 3090022407, 3157196803, 3224371282, 3224371328, 3224372482, 3224387586, + 3228569602, 3627417604, 3627417635, 3627417698, 162, 168, 262, 400, 1792, 2114, 16432, 65568, 131216, 787201, + 1049608, 29388800, 33587216, 50380816, 67174402, 92364800, 403046464, 537395201, 1612185635, 1612185641, + 1612448001, 1813709313, 2149580875, 2149580935, 2149581379, 2149583363, 2151155203, 2283929603, 2888499201, + 2955673671, 2955677703, 3022848007, 3090022531, 3123609603, 3223848450, 3224371490, 3232768002, 3627417607, + 3627419650, 3694592003, 137, 152, 261, 321, 515, 1544, 4164, 6145, 262416, 786688, 1572864, 1574402, 2099208, + 27289600, 33587232, 67174416, 100761632, 134348802, 806092928, 1477836809, 1477837313, 1612185745, + 1612186369, 1637376001, 1880883233, 2149613571, 2418278403, 2955149827, 2955673617, 2955673634, 2955681803, + 3056435267, 3224371270, 3241164802, 3661004803, 3963289603, 138, 268, 784, 1153, 1408, 4224, 8264, 32770, + 32776, 65632, 65664, 393601, 524816, 3147776, 3148804, 4198408, 33587204, 67174432, 201523264, 268697602, + 1612185856, 1612186241, 2150368003, 2913689603, 2955673623, 2955690003, 3039641603, 3090022411, 3224371715, + 3257958402, 3493068994, 3627417632, 164, 518, 2178, 5121, 16448, 16464, 20496, 131232, 787202, 1049616, + 6297608, 14694400, 46182400, 67174404, 67174464, 134348832, 403046528, 537395202, 1074791425, 1612185637, + 1612185667, 1612187137, 1613237249, 1614284801, 1624780801, 1813709825, 2149580939, 2149581063, 2149581123, + 2149586947, 2686976515, 2888499219, 2954887939, 2955673675, 2955706403, 3022848011, 3224371362, 3224374274, + 3291545602, 3627286658, 3627417611, 3627417614, 3694592000, 145, 265, 280, 322, 517, 1552, 3080, 4228, 6152, + 32864, 196801, 262432, 1573376, 1574404, 2097152, 2099216, 12595216, 13644800, 134348804, 134348864, + 806093056, 1074790402, 1444249601, 1477836817, 1612185681, 1612201985, 1616384001, 1813708802, 1838899200, + 2149581570, 2149581825, 2149583873, 2149974403, 2955673633, 2955681795, 2955739203, 3056435331, 3224371274, + 3224371334, 3358720002, 3627417608, 3627417642, 3627418627, 3661004800, 3677798410, 3679901698, 3686195202, + 3761766658, 3963289600, 266, 336, 524, 641, 800, 3328, 4352, 5125, 8256, 8328, 10250, 12289, 20500, 32772, + 41000, 65537, 82000, 131136, 164000, 328000, 393602, 524832, 656000, 1312000, 2624000, 3148808, 4198416, + 5248000, 10496000, 20992000, 25190432, 28339200, 41984000, 83968000, 134348928, 167936000, 268697604, + 268697664, 335872000, 671744000, 1343488000, 1611924225, 1612186112, 1618483201, 1620582401, 1813708816, + 2149583361, 2955673987, 2955804803, 3006054403, 3090022419, 3224371712, 3224403970, 3493069058, 3627417626, + 3627419648, 3681996802, 3719782402, 148, 304, 2306, 3584, 12290, 16528, 98401, 131264, 787204, 1049632, + 3145728, 6297616, 8396816, 23091200, 50380864, 67174408, 268697728, 1074790785, 1612185669, 1813708825 }; diff --git a/src/galois.c b/src/galois.c new file mode 100644 index 0000000..cd9faa8 --- /dev/null +++ b/src/galois.c @@ -0,0 +1,377 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank + */ + +#include +#include +#include +#include +#include + +#include "galois.h" + +#define MAX_GF_INSTANCES 64 +gf_t *gfp_array[MAX_GF_INSTANCES] = { 0 }; +int gfp_is_composite[MAX_GF_INSTANCES] = { 0 }; + +gf_t *galois_get_field_ptr(int w) +{ + if (gfp_array[w] != NULL) { + return gfp_array[w]; + } + + return NULL; +} + +gf_t* galois_init_field(int w, + int mult_type, + int region_type, + int divide_type, + uint64_t prim_poly, + int arg1, + int arg2) +{ + int scratch_size; + void *scratch_memory; + gf_t *gfp; + + if (w <= 0 || w > 32) { + fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w); + assert(0); + } + + gfp = (gf_t *) malloc(sizeof(gf_t)); + if (!gfp) { + fprintf(stderr, "ERROR -- cannot allocate memory for Galois field w=%d\n", w); + assert(0); + } + + scratch_size = gf_scratch_size(w, mult_type, region_type, divide_type, arg1, arg2); + if (!scratch_size) { + fprintf(stderr, "ERROR -- cannot get scratch size for base field w=%d\n", w); + assert(0); + } + + scratch_memory = malloc(scratch_size); + if (!scratch_memory) { + fprintf(stderr, "ERROR -- cannot get scratch memory for base field w=%d\n", w); + assert(0); + } + + if(!gf_init_hard(gfp, + w, + mult_type, + region_type, + divide_type, + prim_poly, + arg1, + arg2, + NULL, + scratch_memory)) + { + fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w); + assert(0); + } + + gfp_is_composite[w] = 0; + return gfp; +} + +gf_t* galois_init_composite_field(int w, + int region_type, + int divide_type, + int degree, + gf_t* base_gf) +{ + int scratch_size; + void *scratch_memory; + gf_t *gfp; + + if (w <= 0 || w > 32) { + fprintf(stderr, "ERROR -- cannot init composite field for w=%d\n", w); + assert(0); + } + + gfp = (gf_t *) malloc(sizeof(gf_t)); + if (!gfp) { + fprintf(stderr, "ERROR -- cannot allocate memory for Galois field w=%d\n", w); + assert(0); + } + + scratch_size = gf_scratch_size(w, GF_MULT_COMPOSITE, region_type, divide_type, degree, 0); + if (!scratch_size) { + fprintf(stderr, "ERROR -- cannot get scratch size for composite field w=%d\n", w); + assert(0); + } + + scratch_memory = malloc(scratch_size); + if (!scratch_memory) { + fprintf(stderr, "ERROR -- cannot get scratch memory for composite field w=%d\n", w); + assert(0); + } + + if(!gf_init_hard(gfp, + w, + GF_MULT_COMPOSITE, + region_type, + divide_type, + 0, + degree, + 0, + base_gf, + scratch_memory)) + { + fprintf(stderr, "ERROR -- cannot init default composite field for w=%d\n", w); + assert(0); + } + gfp_is_composite[w] = 1; + return gfp; +} + +int galois_init_default_field(int w) +{ + if (gfp_array[w] == NULL) { + gfp_array[w] = (gf_t*)malloc(sizeof(gf_t)); + if(gfp_array[w] == NULL) + return ENOMEM; + if (!gf_init_easy(gfp_array[w], w)) + return EINVAL; + } + return 0; +} + +int galois_uninit_field(int w) +{ + int ret = 0; + if (gfp_array[w] != NULL) { + int recursive = 1; + ret = gf_free(gfp_array[w], recursive); + free(gfp_array[w]); + gfp_array[w] = NULL; + } + return ret; +} + +static void galois_init(int w) +{ + if (w <= 0 || w > 32) { + fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w); + assert(0); + } + + switch (galois_init_default_field(w)) { + case ENOMEM: + fprintf(stderr, "ERROR -- cannot allocate memory for Galois field w=%d\n", w); + assert(0); + break; + case EINVAL: + fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w); + assert(0); + break; + } +} + + +static int is_valid_gf(gf_t *gf, int w) +{ + // TODO: I assume we may eventually + // want to do w=64 and 128, so w + // will be needed to perform this check + (void)w; + + if (gf == NULL) { + return 0; + } + if (gf->multiply.w32 == NULL) { + return 0; + } + if (gf->multiply_region.w32 == NULL) { + return 0; + } + if (gf->divide.w32 == NULL) { + return 0; + } + if (gf->inverse.w32 == NULL) { + return 0; + } + if (gf->extract_word.w32 == NULL) { + return 0; + } + + return 1; +} + +void galois_change_technique(gf_t *gf, int w) +{ + if (w <= 0 || w > 32) { + fprintf(stderr, "ERROR -- cannot support Galois field for w=%d\n", w); + assert(0); + } + + if (!is_valid_gf(gf, w)) { + fprintf(stderr, "ERROR -- overriding with invalid Galois field for w=%d\n", w); + assert(0); + } + + if (gfp_array[w] != NULL) { + gf_free(gfp_array[w], gfp_is_composite[w]); + } + + gfp_array[w] = gf; +} + +int galois_single_multiply(int x, int y, int w) +{ + if (x == 0 || y == 0) return 0; + + if (gfp_array[w] == NULL) { + galois_init(w); + } + + if (w <= 32) { + return gfp_array[w]->multiply.w32(gfp_array[w], x, y); + } else { + fprintf(stderr, "ERROR -- Galois field not implemented for w=%d\n", w); + return 0; + } +} + +int galois_single_divide(int x, int y, int w) +{ + if (x == 0) return 0; + if (y == 0) return -1; + + if (gfp_array[w] == NULL) { + galois_init(w); + } + + if (w <= 32) { + return gfp_array[w]->divide.w32(gfp_array[w], x, y); + } else { + fprintf(stderr, "ERROR -- Galois field not implemented for w=%d\n", w); + return 0; + } +} + +void galois_w08_region_multiply(char *region, /* Region to multiply */ + int multby, /* Number to multiply by */ + int nbytes, /* Number of bytes in region */ + char *r2, /* If r2 != NULL, products go here */ + int add) +{ + if (gfp_array[8] == NULL) { + galois_init(8); + } + gfp_array[8]->multiply_region.w32(gfp_array[8], region, r2, multby, nbytes, add); +} + +void galois_w16_region_multiply(char *region, /* Region to multiply */ + int multby, /* Number to multiply by */ + int nbytes, /* Number of bytes in region */ + char *r2, /* If r2 != NULL, products go here */ + int add) +{ + if (gfp_array[16] == NULL) { + galois_init(16); + } + gfp_array[16]->multiply_region.w32(gfp_array[16], region, r2, multby, nbytes, add); +} + + +void galois_w32_region_multiply(char *region, /* Region to multiply */ + int multby, /* Number to multiply by */ + int nbytes, /* Number of bytes in region */ + char *r2, /* If r2 != NULL, products go here */ + int add) +{ + if (gfp_array[32] == NULL) { + galois_init(32); + } + gfp_array[32]->multiply_region.w32(gfp_array[32], region, r2, multby, nbytes, add); +} + +void galois_w8_region_xor(void *src, void *dest, int nbytes) +{ + if (gfp_array[8] == NULL) { + galois_init(8); + } + gfp_array[8]->multiply_region.w32(gfp_array[32], src, dest, 1, nbytes, 1); +} + +void galois_w16_region_xor(void *src, void *dest, int nbytes) +{ + if (gfp_array[16] == NULL) { + galois_init(16); + } + gfp_array[16]->multiply_region.w32(gfp_array[16], src, dest, 1, nbytes, 1); +} + +void galois_w32_region_xor(void *src, void *dest, int nbytes) +{ + if (gfp_array[32] == NULL) { + galois_init(32); + } + gfp_array[32]->multiply_region.w32(gfp_array[32], src, dest, 1, nbytes, 1); +} + +void galois_region_xor(char *src, char *dest, int nbytes) +{ + if (nbytes >= 16) { + galois_w32_region_xor(src, dest, nbytes); + } else { + int i = 0; + for (i = 0; i < nbytes; i++) { + *dest ^= *src; + dest++; + src++; + } + } +} + +int galois_inverse(int y, int w) +{ + if (y == 0) return -1; + return galois_single_divide(1, y, w); +} diff --git a/src/jerasure.c b/src/jerasure.c new file mode 100644 index 0000000..6874a8a --- /dev/null +++ b/src/jerasure.c @@ -0,0 +1,1485 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank + */ + +#include +#include +#include +#include + +#include "galois.h" +#include "jerasure.h" + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +static double jerasure_total_xor_bytes = 0; +static double jerasure_total_gf_bytes = 0; +static double jerasure_total_memcpy_bytes = 0; + +void jerasure_print_matrix(int *m, int rows, int cols, int w) +{ + int i, j; + int fw; + char s[30]; + unsigned int w2; + + if (w == 32) { + fw = 10; + } else { + w2 = (1 << w); + sprintf(s, "%u", w2-1); + fw = strlen(s); + } + + for (i = 0; i < rows; i++) { + for (j = 0; j < cols; j++) { + if (j != 0) printf(" "); + printf("%*u", fw, m[i*cols+j]); + } + printf("\n"); + } +} + +void jerasure_print_bitmatrix(int *m, int rows, int cols, int w) +{ + int i, j; + + for (i = 0; i < rows; i++) { + if (i != 0 && i%w == 0) printf("\n"); + for (j = 0; j < cols; j++) { + if (j != 0 && j%w == 0) printf(" "); + printf("%d", m[i*cols+j]); + } + printf("\n"); + } +} + +int jerasure_make_decoding_matrix(int k, int m, int w, int *matrix, int *erased, int *decoding_matrix, int *dm_ids) +{ + int i, j, *tmpmat; + + j = 0; + for (i = 0; j < k; i++) { + if (erased[i] == 0) { + dm_ids[j] = i; + j++; + } + } + + tmpmat = talloc(int, k*k); + if (tmpmat == NULL) { return -1; } + for (i = 0; i < k; i++) { + if (dm_ids[i] < k) { + for (j = 0; j < k; j++) tmpmat[i*k+j] = 0; + tmpmat[i*k+dm_ids[i]] = 1; + } else { + for (j = 0; j < k; j++) { + tmpmat[i*k+j] = matrix[(dm_ids[i]-k)*k+j]; + } + } + } + + i = jerasure_invert_matrix(tmpmat, decoding_matrix, k, w); + free(tmpmat); + return i; +} + +/* Internal Routine */ +int jerasure_make_decoding_bitmatrix(int k, int m, int w, int *matrix, int *erased, int *decoding_matrix, int *dm_ids) +{ + int i, j, *tmpmat; + int index, mindex; + + j = 0; + for (i = 0; j < k; i++) { + if (erased[i] == 0) { + dm_ids[j] = i; + j++; + } + } + + tmpmat = talloc(int, k*k*w*w); + if (tmpmat == NULL) { return -1; } + for (i = 0; i < k; i++) { + if (dm_ids[i] < k) { + index = i*k*w*w; + for (j = 0; j < k*w*w; j++) tmpmat[index+j] = 0; + index = i*k*w*w+dm_ids[i]*w; + for (j = 0; j < w; j++) { + tmpmat[index] = 1; + index += (k*w+1); + } + } else { + index = i*k*w*w; + mindex = (dm_ids[i]-k)*k*w*w; + for (j = 0; j < k*w*w; j++) { + tmpmat[index+j] = matrix[mindex+j]; + } + } + } + + i = jerasure_invert_bitmatrix(tmpmat, decoding_matrix, k*w); + free(tmpmat); + return i; +} + +int jerasure_matrix_decode(int k, int m, int w, int *matrix, int row_k_ones, int *erasures, + char **data_ptrs, char **coding_ptrs, int size) +{ + int i, edd, lastdrive; + int *tmpids; + int *erased, *decoding_matrix, *dm_ids; + + if (w != 8 && w != 16 && w != 32) return -1; + + erased = jerasure_erasures_to_erased(k, m, erasures); + if (erased == NULL) return -1; + + /* Find the number of data drives failed */ + + lastdrive = k; + + edd = 0; + for (i = 0; i < k; i++) { + if (erased[i]) { + edd++; + lastdrive = i; + } + } + + /* You only need to create the decoding matrix in the following cases: + + 1. edd > 0 and row_k_ones is false. + 2. edd > 0 and row_k_ones is true and coding device 0 has been erased. + 3. edd > 1 + + We're going to use lastdrive to denote when to stop decoding data. + At this point in the code, it is equal to the last erased data device. + However, if we can't use the parity row to decode it (i.e. row_k_ones=0 + or erased[k] = 1, we're going to set it to k so that the decoding + pass will decode all data. + */ + + if (!row_k_ones || erased[k]) lastdrive = k; + + dm_ids = NULL; + decoding_matrix = NULL; + + if (edd > 1 || (edd > 0 && (!row_k_ones || erased[k]))) { + dm_ids = talloc(int, k); + if (dm_ids == NULL) { + free(erased); + return -1; + } + + decoding_matrix = talloc(int, k*k); + if (decoding_matrix == NULL) { + free(erased); + free(dm_ids); + return -1; + } + + if (jerasure_make_decoding_matrix(k, m, w, matrix, erased, decoding_matrix, dm_ids) < 0) { + free(erased); + free(dm_ids); + free(decoding_matrix); + return -1; + } + } + + /* Decode the data drives. + If row_k_ones is true and coding device 0 is intact, then only decode edd-1 drives. + This is done by stopping at lastdrive. + We test whether edd > 0 so that we can exit the loop early if we're done. + */ + + for (i = 0; edd > 0 && i < lastdrive; i++) { + if (erased[i]) { + jerasure_matrix_dotprod(k, w, decoding_matrix+(i*k), dm_ids, i, data_ptrs, coding_ptrs, size); + edd--; + } + } + + /* Then if necessary, decode drive lastdrive */ + + if (edd > 0) { + tmpids = talloc(int, k); + if (!tmpids) { + free(erased); + free(dm_ids); + free(decoding_matrix); + return -1; + } + for (i = 0; i < k; i++) { + tmpids[i] = (i < lastdrive) ? i : i+1; + } + jerasure_matrix_dotprod(k, w, matrix, tmpids, lastdrive, data_ptrs, coding_ptrs, size); + free(tmpids); + } + + /* Finally, re-encode any erased coding devices */ + + for (i = 0; i < m; i++) { + if (erased[k+i]) { + jerasure_matrix_dotprod(k, w, matrix+(i*k), NULL, i+k, data_ptrs, coding_ptrs, size); + } + } + + free(erased); + if (dm_ids != NULL) free(dm_ids); + if (decoding_matrix != NULL) free(decoding_matrix); + + return 0; +} + + +int *jerasure_matrix_to_bitmatrix(int k, int m, int w, int *matrix) +{ + int *bitmatrix; + int rowelts, rowindex, colindex, elt, i, j, l, x; + + if (matrix == NULL) { return NULL; } + + bitmatrix = talloc(int, k*m*w*w); + if (!bitmatrix) return NULL; + + rowelts = k * w; + rowindex = 0; + + for (i = 0; i < m; i++) { + colindex = rowindex; + for (j = 0; j < k; j++) { + elt = matrix[i*k+j]; + for (x = 0; x < w; x++) { + for (l = 0; l < w; l++) { + bitmatrix[colindex+x+l*rowelts] = ((elt & (1 << l)) ? 1 : 0); + } + elt = galois_single_multiply(elt, 2, w); + } + colindex += w; + } + rowindex += rowelts * w; + } + return bitmatrix; +} + +void jerasure_matrix_encode(int k, int m, int w, int *matrix, + char **data_ptrs, char **coding_ptrs, int size) +{ + int i; + + if (w != 8 && w != 16 && w != 32) { + fprintf(stderr, "ERROR: jerasure_matrix_encode() and w is not 8, 16 or 32\n"); + assert(0); + } + + for (i = 0; i < m; i++) { + jerasure_matrix_dotprod(k, w, matrix+(i*k), NULL, k+i, data_ptrs, coding_ptrs, size); + } +} + +void jerasure_bitmatrix_dotprod(int k, int w, int *bitmatrix_row, + int *src_ids, int dest_id, + char **data_ptrs, char **coding_ptrs, int size, int packetsize) +{ + int j, sindex, pstarted, index, x, y; + char *dptr, *pptr, *bdptr, *bpptr; + + if (size%(w*packetsize) != 0) { + fprintf(stderr, "jerasure_bitmatrix_dotprod - size%c(w*packetsize)) must = 0\n", '%'); + assert(0); + } + + bpptr = (dest_id < k) ? data_ptrs[dest_id] : coding_ptrs[dest_id-k]; + + for (sindex = 0; sindex < size; sindex += (packetsize*w)) { + index = 0; + for (j = 0; j < w; j++) { + pstarted = 0; + pptr = bpptr + sindex + j*packetsize; + for (x = 0; x < k; x++) { + if (src_ids == NULL) { + bdptr = data_ptrs[x]; + } else if (src_ids[x] < k) { + bdptr = data_ptrs[src_ids[x]]; + } else { + bdptr = coding_ptrs[src_ids[x]-k]; + } + for (y = 0; y < w; y++) { + if (bitmatrix_row[index]) { + dptr = bdptr + sindex + y*packetsize; + if (!pstarted) { + memcpy(pptr, dptr, packetsize); + jerasure_total_memcpy_bytes += packetsize; + pstarted = 1; + } else { + galois_region_xor(dptr, pptr, packetsize); + jerasure_total_xor_bytes += packetsize; + } + } + index++; + } + } + } + } +} + +void jerasure_do_parity(int k, char **data_ptrs, char *parity_ptr, int size) +{ + int i; + + memcpy(parity_ptr, data_ptrs[0], size); + jerasure_total_memcpy_bytes += size; + + for (i = 1; i < k; i++) { + galois_region_xor(data_ptrs[i], parity_ptr, size); + jerasure_total_xor_bytes += size; + } +} + +int jerasure_invert_matrix(int *mat, int *inv, int rows, int w) +{ + int cols, i, j, k, x, rs2; + int row_start, tmp, inverse; + + cols = rows; + + k = 0; + for (i = 0; i < rows; i++) { + for (j = 0; j < cols; j++) { + inv[k] = (i == j) ? 1 : 0; + k++; + } + } + + /* First -- convert into upper triangular */ + for (i = 0; i < cols; i++) { + row_start = cols*i; + + /* Swap rows if we ave a zero i,i element. If we can't swap, then the + matrix was not invertible */ + + if (mat[row_start+i] == 0) { + for (j = i+1; j < rows && mat[cols*j+i] == 0; j++) ; + if (j == rows) return -1; + rs2 = j*cols; + for (k = 0; k < cols; k++) { + tmp = mat[row_start+k]; + mat[row_start+k] = mat[rs2+k]; + mat[rs2+k] = tmp; + tmp = inv[row_start+k]; + inv[row_start+k] = inv[rs2+k]; + inv[rs2+k] = tmp; + } + } + + /* Multiply the row by 1/element i,i */ + tmp = mat[row_start+i]; + if (tmp != 1) { + inverse = galois_single_divide(1, tmp, w); + for (j = 0; j < cols; j++) { + mat[row_start+j] = galois_single_multiply(mat[row_start+j], inverse, w); + inv[row_start+j] = galois_single_multiply(inv[row_start+j], inverse, w); + } + } + + /* Now for each j>i, add A_ji*Ai to Aj */ + k = row_start+i; + for (j = i+1; j != cols; j++) { + k += cols; + if (mat[k] != 0) { + if (mat[k] == 1) { + rs2 = cols*j; + for (x = 0; x < cols; x++) { + mat[rs2+x] ^= mat[row_start+x]; + inv[rs2+x] ^= inv[row_start+x]; + } + } else { + tmp = mat[k]; + rs2 = cols*j; + for (x = 0; x < cols; x++) { + mat[rs2+x] ^= galois_single_multiply(tmp, mat[row_start+x], w); + inv[rs2+x] ^= galois_single_multiply(tmp, inv[row_start+x], w); + } + } + } + } + } + + /* Now the matrix is upper triangular. Start at the top and multiply down */ + + for (i = rows-1; i >= 0; i--) { + row_start = i*cols; + for (j = 0; j < i; j++) { + rs2 = j*cols; + if (mat[rs2+i] != 0) { + tmp = mat[rs2+i]; + mat[rs2+i] = 0; + for (k = 0; k < cols; k++) { + inv[rs2+k] ^= galois_single_multiply(tmp, inv[row_start+k], w); + } + } + } + } + return 0; +} + +int jerasure_invertible_matrix(int *mat, int rows, int w) +{ + int cols, i, j, k, x, rs2; + int row_start, tmp, inverse; + + cols = rows; + + /* First -- convert into upper triangular */ + for (i = 0; i < cols; i++) { + row_start = cols*i; + + /* Swap rows if we ave a zero i,i element. If we can't swap, then the + matrix was not invertible */ + + if (mat[row_start+i] == 0) { + for (j = i+1; j < rows && mat[cols*j+i] == 0; j++) ; + if (j == rows) return 0; + rs2 = j*cols; + for (k = 0; k < cols; k++) { + tmp = mat[row_start+k]; + mat[row_start+k] = mat[rs2+k]; + mat[rs2+k] = tmp; + } + } + + /* Multiply the row by 1/element i,i */ + tmp = mat[row_start+i]; + if (tmp != 1) { + inverse = galois_single_divide(1, tmp, w); + for (j = 0; j < cols; j++) { + mat[row_start+j] = galois_single_multiply(mat[row_start+j], inverse, w); + } + } + + /* Now for each j>i, add A_ji*Ai to Aj */ + k = row_start+i; + for (j = i+1; j != cols; j++) { + k += cols; + if (mat[k] != 0) { + if (mat[k] == 1) { + rs2 = cols*j; + for (x = 0; x < cols; x++) { + mat[rs2+x] ^= mat[row_start+x]; + } + } else { + tmp = mat[k]; + rs2 = cols*j; + for (x = 0; x < cols; x++) { + mat[rs2+x] ^= galois_single_multiply(tmp, mat[row_start+x], w); + } + } + } + } + } + return 1; +} + +/* Converts a list-style version of the erasures into an array of k+m elements + where the element = 1 if the index has been erased, and zero otherwise */ + +int *jerasure_erasures_to_erased(int k, int m, int *erasures) +{ + int td; + int t_non_erased; + int *erased; + int i; + + td = k+m; + erased = talloc(int, td); + if (erased == NULL) return NULL; + t_non_erased = td; + + for (i = 0; i < td; i++) erased[i] = 0; + + for (i = 0; erasures[i] != -1; i++) { + if (erased[erasures[i]] == 0) { + erased[erasures[i]] = 1; + t_non_erased--; + if (t_non_erased < k) { + free(erased); + return NULL; + } + } + } + return erased; +} + +void jerasure_free_schedule(int **schedule) +{ + int i; + + for (i = 0; schedule[i][0] >= 0; i++) free(schedule[i]); + free(schedule[i]); + free(schedule); +} + +void jerasure_free_schedule_cache(int k, int m, int ***cache) +{ + int e1, e2; + + if (m != 2) { + fprintf(stderr, "jerasure_free_schedule_cache(): m must equal 2\n"); + assert(0); + } + + for (e1 = 0; e1 < k+m; e1++) { + for (e2 = 0; e2 < e1; e2++) { + jerasure_free_schedule(cache[e1*(k+m)+e2]); + } + jerasure_free_schedule(cache[e1*(k+m)+e1]); + } + free(cache); +} + +void jerasure_matrix_dotprod(int k, int w, int *matrix_row, + int *src_ids, int dest_id, + char **data_ptrs, char **coding_ptrs, int size) +{ + int init; + char *dptr, *sptr; + int i; + + if (w != 1 && w != 8 && w != 16 && w != 32) { + fprintf(stderr, "ERROR: jerasure_matrix_dotprod() called and w is not 1, 8, 16 or 32\n"); + assert(0); + } + + init = 0; + + dptr = (dest_id < k) ? data_ptrs[dest_id] : coding_ptrs[dest_id-k]; + + /* First copy or xor any data that does not need to be multiplied by a factor */ + + for (i = 0; i < k; i++) { + if (matrix_row[i] == 1) { + if (src_ids == NULL) { + sptr = data_ptrs[i]; + } else if (src_ids[i] < k) { + sptr = data_ptrs[src_ids[i]]; + } else { + sptr = coding_ptrs[src_ids[i]-k]; + } + if (init == 0) { + memcpy(dptr, sptr, size); + jerasure_total_memcpy_bytes += size; + init = 1; + } else { + galois_region_xor(sptr, dptr, size); + jerasure_total_xor_bytes += size; + } + } + } + + /* Now do the data that needs to be multiplied by a factor */ + + for (i = 0; i < k; i++) { + if (matrix_row[i] != 0 && matrix_row[i] != 1) { + if (src_ids == NULL) { + sptr = data_ptrs[i]; + } else if (src_ids[i] < k) { + sptr = data_ptrs[src_ids[i]]; + } else { + sptr = coding_ptrs[src_ids[i]-k]; + } + switch (w) { + case 8: galois_w08_region_multiply(sptr, matrix_row[i], size, dptr, init); break; + case 16: galois_w16_region_multiply(sptr, matrix_row[i], size, dptr, init); break; + case 32: galois_w32_region_multiply(sptr, matrix_row[i], size, dptr, init); break; + } + jerasure_total_gf_bytes += size; + init = 1; + } + } +} + + +int jerasure_bitmatrix_decode(int k, int m, int w, int *bitmatrix, int row_k_ones, int *erasures, + char **data_ptrs, char **coding_ptrs, int size, int packetsize) +{ + int i; + int *erased; + int *decoding_matrix; + int *dm_ids; + int edd, *tmpids, lastdrive; + + erased = jerasure_erasures_to_erased(k, m, erasures); + if (erased == NULL) return -1; + + /* See jerasure_matrix_decode for the logic of this routine. This one works just like + it, but calls the bitmatrix ops instead */ + + lastdrive = k; + + edd = 0; + for (i = 0; i < k; i++) { + if (erased[i]) { + edd++; + lastdrive = i; + } + } + + if (row_k_ones != 1 || erased[k]) lastdrive = k; + + dm_ids = NULL; + decoding_matrix = NULL; + + if (edd > 1 || (edd > 0 && (row_k_ones != 1 || erased[k]))) { + + dm_ids = talloc(int, k); + if (dm_ids == NULL) { + free(erased); + return -1; + } + + decoding_matrix = talloc(int, k*k*w*w); + if (decoding_matrix == NULL) { + free(erased); + free(dm_ids); + return -1; + } + + if (jerasure_make_decoding_bitmatrix(k, m, w, bitmatrix, erased, decoding_matrix, dm_ids) < 0) { + free(erased); + free(dm_ids); + free(decoding_matrix); + return -1; + } + } + + for (i = 0; edd > 0 && i < lastdrive; i++) { + if (erased[i]) { + jerasure_bitmatrix_dotprod(k, w, decoding_matrix+i*k*w*w, dm_ids, i, data_ptrs, coding_ptrs, size, packetsize); + edd--; + } + } + + if (edd > 0) { + tmpids = talloc(int, k); + if (!tmpids) { + free(erased); + free(dm_ids); + free(decoding_matrix); + return -1; + } + for (i = 0; i < k; i++) { + tmpids[i] = (i < lastdrive) ? i : i+1; + } + jerasure_bitmatrix_dotprod(k, w, bitmatrix, tmpids, lastdrive, data_ptrs, coding_ptrs, size, packetsize); + free(tmpids); + } + + for (i = 0; i < m; i++) { + if (erased[k+i]) { + jerasure_bitmatrix_dotprod(k, w, bitmatrix+i*k*w*w, NULL, k+i, data_ptrs, coding_ptrs, size, packetsize); + } + } + + free(erased); + if (dm_ids != NULL) free(dm_ids); + if (decoding_matrix != NULL) free(decoding_matrix); + + return 0; +} + +static char **set_up_ptrs_for_scheduled_decoding(int k, int m, int *erasures, char **data_ptrs, char **coding_ptrs) +{ + int ddf, cdf; + int *erased; + char **ptrs; + int i, j, x; + + ddf = 0; + cdf = 0; + for (i = 0; erasures[i] != -1; i++) { + if (erasures[i] < k) ddf++; else cdf++; + } + + erased = jerasure_erasures_to_erased(k, m, erasures); + if (erased == NULL) return NULL; + + /* Set up ptrs. It will be as follows: + + - If data drive i has not failed, then ptrs[i] = data_ptrs[i]. + - If data drive i has failed, then ptrs[i] = coding_ptrs[j], where j is the + lowest unused non-failed coding drive. + - Elements k to k+ddf-1 are data_ptrs[] of the failed data drives. + - Elements k+ddf to k+ddf+cdf-1 are coding_ptrs[] of the failed data drives. + + The array row_ids contains the ids of ptrs. + The array ind_to_row_ids contains the row_id of drive i. + + However, we're going to set row_ids and ind_to_row in a different procedure. + */ + + ptrs = talloc(char *, k+m); + if (!ptrs) { + free(erased); + return NULL; + } + + j = k; + x = k; + for (i = 0; i < k; i++) { + if (erased[i] == 0) { + ptrs[i] = data_ptrs[i]; + } else { + while (erased[j]) j++; + ptrs[i] = coding_ptrs[j-k]; + j++; + ptrs[x] = data_ptrs[i]; + x++; + } + } + for (i = k; i < k+m; i++) { + if (erased[i]) { + ptrs[x] = coding_ptrs[i-k]; + x++; + } + } + free(erased); + return ptrs; +} + +static int set_up_ids_for_scheduled_decoding(int k, int m, int *erasures, int *row_ids, int *ind_to_row) +{ + int ddf, cdf; + int *erased; + int i, j, x; + + ddf = 0; + cdf = 0; + for (i = 0; erasures[i] != -1; i++) { + if (erasures[i] < k) ddf++; else cdf++; + } + + erased = jerasure_erasures_to_erased(k, m, erasures); + if (erased == NULL) return -1; + + /* See set_up_ptrs_for_scheduled_decoding for how these are set */ + + j = k; + x = k; + for (i = 0; i < k; i++) { + if (erased[i] == 0) { + row_ids[i] = i; + ind_to_row[i] = i; + } else { + while (erased[j]) j++; + row_ids[i] = j; + ind_to_row[j] = i; + j++; + row_ids[x] = i; + ind_to_row[i] = x; + x++; + } + } + for (i = k; i < k+m; i++) { + if (erased[i]) { + row_ids[x] = i; + ind_to_row[i] = x; + x++; + } + } + free(erased); + return 0; +} + +static int **jerasure_generate_decoding_schedule(int k, int m, int w, int *bitmatrix, int *erasures, int smart) +{ + int i, j, x, drive, y, index, z; + int *decoding_matrix, *inverse, *real_decoding_matrix; + int *ptr; + int *row_ids; + int *ind_to_row; + int ddf, cdf; + int **schedule; + int *b1, *b2; + + /* First, figure out the number of data drives that have failed, and the + number of coding drives that have failed: ddf and cdf */ + + ddf = 0; + cdf = 0; + for (i = 0; erasures[i] != -1; i++) { + if (erasures[i] < k) ddf++; else cdf++; + } + + row_ids = talloc(int, k+m); + if (!row_ids) return NULL; + ind_to_row = talloc(int, k+m); + if (!ind_to_row) { + free(row_ids); + return NULL; + } + + if (set_up_ids_for_scheduled_decoding(k, m, erasures, row_ids, ind_to_row) < 0) { + free(row_ids); + free(ind_to_row); + return NULL; + } + + /* Now, we're going to create one decoding matrix which is going to + decode everything with one call. The hope is that the scheduler + will do a good job. This matrix has w*e rows, where e is the + number of erasures (ddf+cdf) */ + + real_decoding_matrix = talloc(int, k*w*(cdf+ddf)*w); + if (!real_decoding_matrix) { + free(row_ids); + free(ind_to_row); + return NULL; + } + + /* First, if any data drives have failed, then initialize the first + ddf*w rows of the decoding matrix from the standard decoding + matrix inversion */ + + if (ddf > 0) { + + decoding_matrix = talloc(int, k*k*w*w); + if (!decoding_matrix) { + free(row_ids); + free(ind_to_row); + return NULL; + } + ptr = decoding_matrix; + for (i = 0; i < k; i++) { + if (row_ids[i] == i) { + bzero(ptr, k*w*w*sizeof(int)); + for (x = 0; x < w; x++) { + ptr[x+i*w+x*k*w] = 1; + } + } else { + memcpy(ptr, bitmatrix+k*w*w*(row_ids[i]-k), k*w*w*sizeof(int)); + } + ptr += (k*w*w); + } + inverse = talloc(int, k*k*w*w); + if (!inverse) { + free(row_ids); + free(ind_to_row); + free(decoding_matrix); + return NULL; + } + jerasure_invert_bitmatrix(decoding_matrix, inverse, k*w); + +/* printf("\nMatrix to invert\n"); + jerasure_print_bitmatrix(decoding_matrix, k*w, k*w, w); + printf("\n"); + printf("\nInverse\n"); + jerasure_print_bitmatrix(inverse, k*w, k*w, w); + printf("\n"); */ + + free(decoding_matrix); + ptr = real_decoding_matrix; + for (i = 0; i < ddf; i++) { + memcpy(ptr, inverse+k*w*w*row_ids[k+i], sizeof(int)*k*w*w); + ptr += (k*w*w); + } + free(inverse); + } + + /* Next, here comes the hard part. For each coding node that needs + to be decoded, you start by putting its rows of the distribution + matrix into the decoding matrix. If there were no failed data + nodes, then you're done. However, if there have been failed + data nodes, then you need to modify the columns that correspond + to the data nodes. You do that by first zeroing them. Then + whereever there is a one in the distribution matrix, you XOR + in the corresponding row from the failed data node's entry in + the decoding matrix. The whole process kind of makes my head + spin, but it works. + */ + + for (x = 0; x < cdf; x++) { + drive = row_ids[x+ddf+k]-k; + ptr = real_decoding_matrix + k*w*w*(ddf+x); + memcpy(ptr, bitmatrix+drive*k*w*w, sizeof(int)*k*w*w); + + for (i = 0; i < k; i++) { + if (row_ids[i] != i) { + for (j = 0; j < w; j++) { + bzero(ptr+j*k*w+i*w, sizeof(int)*w); + } + } + } + + /* There's the yucky part */ + + index = drive*k*w*w; + for (i = 0; i < k; i++) { + if (row_ids[i] != i) { + b1 = real_decoding_matrix+(ind_to_row[i]-k)*k*w*w; + for (j = 0; j < w; j++) { + b2 = ptr + j*k*w; + for (y = 0; y < w; y++) { + if (bitmatrix[index+j*k*w+i*w+y]) { + for (z = 0; z < k*w; z++) { + b2[z] = b2[z] ^ b1[z+y*k*w]; + } + } + } + } + } + } + } + +/* + printf("\n\nReal Decoding Matrix\n\n"); + jerasure_print_bitmatrix(real_decoding_matrix, (ddf+cdf)*w, k*w, w); + printf("\n"); */ + if (smart) { + schedule = jerasure_smart_bitmatrix_to_schedule(k, ddf+cdf, w, real_decoding_matrix); + } else { + schedule = jerasure_dumb_bitmatrix_to_schedule(k, ddf+cdf, w, real_decoding_matrix); + } + free(row_ids); + free(ind_to_row); + free(real_decoding_matrix); + return schedule; +} + +int jerasure_schedule_decode_lazy(int k, int m, int w, int *bitmatrix, int *erasures, + char **data_ptrs, char **coding_ptrs, int size, int packetsize, + int smart) +{ + int i, tdone; + char **ptrs; + int **schedule; + + ptrs = set_up_ptrs_for_scheduled_decoding(k, m, erasures, data_ptrs, coding_ptrs); + if (ptrs == NULL) return -1; + + schedule = jerasure_generate_decoding_schedule(k, m, w, bitmatrix, erasures, smart); + if (schedule == NULL) { + free(ptrs); + return -1; + } + + for (tdone = 0; tdone < size; tdone += packetsize*w) { + jerasure_do_scheduled_operations(ptrs, schedule, packetsize); + for (i = 0; i < k+m; i++) ptrs[i] += (packetsize*w); + } + + jerasure_free_schedule(schedule); + free(ptrs); + + return 0; +} + +int jerasure_schedule_decode_cache(int k, int m, int w, int ***scache, int *erasures, + char **data_ptrs, char **coding_ptrs, int size, int packetsize) +{ + int i, tdone; + char **ptrs; + int **schedule; + int index; + + if (erasures[1] == -1) { + index = erasures[0]*(k+m) + erasures[0]; + } else if (erasures[2] == -1) { + index = erasures[0]*(k+m) + erasures[1]; + } else { + return -1; + } + + schedule = scache[index]; + + ptrs = set_up_ptrs_for_scheduled_decoding(k, m, erasures, data_ptrs, coding_ptrs); + if (ptrs == NULL) return -1; + + + for (tdone = 0; tdone < size; tdone += packetsize*w) { + jerasure_do_scheduled_operations(ptrs, schedule, packetsize); + for (i = 0; i < k+m; i++) ptrs[i] += (packetsize*w); + } + + free(ptrs); + + return 0; +} + +/* This only works when m = 2 */ + +int ***jerasure_generate_schedule_cache(int k, int m, int w, int *bitmatrix, int smart) +{ + int ***scache; + int erasures[3]; + int e1, e2; + + /* Ok -- this is yucky, but it's how I'm doing it. You will make an index out + of erasures, which will be e1*(k+m)+(e2). If there is no e2, then e2 = e1. + Isn't that clever and confusing. Sorry. + + We're not going to worry about ordering -- in other words, the schedule for + e1,e2 will be the same as e2,e1. They will have the same pointer -- the + schedule will not be duplicated. */ + + if (m != 2) return NULL; + + scache = talloc(int **, (k+m)*(k+m+1)); + if (scache == NULL) return NULL; + + for (e1 = 0; e1 < k+m; e1++) { + erasures[0] = e1; + for (e2 = 0; e2 < e1; e2++) { + erasures[1] = e2; + erasures[2] = -1; + scache[e1*(k+m)+e2] = jerasure_generate_decoding_schedule(k, m, w, bitmatrix, erasures, smart); + scache[e2*(k+m)+e1] = scache[e1*(k+m)+e2]; + } + erasures[1] = -1; + scache[e1*(k+m)+e1] = jerasure_generate_decoding_schedule(k, m, w, bitmatrix, erasures, smart); + } + return scache; + +} + +int jerasure_invert_bitmatrix(int *mat, int *inv, int rows) +{ + int cols, i, j, k; + int tmp; + + cols = rows; + + k = 0; + for (i = 0; i < rows; i++) { + for (j = 0; j < cols; j++) { + inv[k] = (i == j) ? 1 : 0; + k++; + } + } + + /* First -- convert into upper triangular */ + + for (i = 0; i < cols; i++) { + + /* Swap rows if we have a zero i,i element. If we can't swap, then the + matrix was not invertible */ + + if ((mat[i*cols+i]) == 0) { + for (j = i+1; j < rows && (mat[j*cols+i]) == 0; j++) ; + if (j == rows) return -1; + for (k = 0; k < cols; k++) { + tmp = mat[i*cols+k]; mat[i*cols+k] = mat[j*cols+k]; mat[j*cols+k] = tmp; + tmp = inv[i*cols+k]; inv[i*cols+k] = inv[j*cols+k]; inv[j*cols+k] = tmp; + } + } + + /* Now for each j>i, add A_ji*Ai to Aj */ + for (j = i+1; j != rows; j++) { + if (mat[j*cols+i] != 0) { + for (k = 0; k < cols; k++) { + mat[j*cols+k] ^= mat[i*cols+k]; + inv[j*cols+k] ^= inv[i*cols+k]; + } + } + } + } + + /* Now the matrix is upper triangular. Start at the top and multiply down */ + + for (i = rows-1; i >= 0; i--) { + for (j = 0; j < i; j++) { + if (mat[j*cols+i]) { + for (k = 0; k < cols; k++) { + mat[j*cols+k] ^= mat[i*cols+k]; + inv[j*cols+k] ^= inv[i*cols+k]; + } + } + } + } + return 0; +} + +int jerasure_invertible_bitmatrix(int *mat, int rows) +{ + int cols, i, j, k; + int tmp; + + cols = rows; + + /* First -- convert into upper triangular */ + + for (i = 0; i < cols; i++) { + + /* Swap rows if we have a zero i,i element. If we can't swap, then the + matrix was not invertible */ + + if ((mat[i*cols+i]) == 0) { + for (j = i+1; j < rows && (mat[j*cols+i]) == 0; j++) ; + if (j == rows) return 0; + for (k = 0; k < cols; k++) { + tmp = mat[i*cols+k]; mat[i*cols+k] = mat[j*cols+k]; mat[j*cols+k] = tmp; + } + } + + /* Now for each j>i, add A_ji*Ai to Aj */ + for (j = i+1; j != rows; j++) { + if (mat[j*cols+i] != 0) { + for (k = 0; k < cols; k++) { + mat[j*cols+k] ^= mat[i*cols+k]; + } + } + } + } + return 1; +} + + +int *jerasure_matrix_multiply(int *m1, int *m2, int r1, int c1, int r2, int c2, int w) +{ + int *product, i, j, k; + + product = (int *) malloc(sizeof(int)*r1*c2); + for (i = 0; i < r1*c2; i++) product[i] = 0; + + for (i = 0; i < r1; i++) { + for (j = 0; j < c2; j++) { + for (k = 0; k < r2; k++) { + product[i*c2+j] ^= galois_single_multiply(m1[i*c1+k], m2[k*c2+j], w); + } + } + } + return product; +} + +void jerasure_get_stats(double *fill_in) +{ + fill_in[0] = jerasure_total_xor_bytes; + fill_in[1] = jerasure_total_gf_bytes; + fill_in[2] = jerasure_total_memcpy_bytes; + jerasure_total_xor_bytes = 0; + jerasure_total_gf_bytes = 0; + jerasure_total_memcpy_bytes = 0; +} + +void jerasure_do_scheduled_operations(char **ptrs, int **operations, int packetsize) +{ + char *sptr; + char *dptr; + int op; + + for (op = 0; operations[op][0] >= 0; op++) { + sptr = ptrs[operations[op][0]] + operations[op][1]*packetsize; + dptr = ptrs[operations[op][2]] + operations[op][3]*packetsize; + if (operations[op][4]) { +/* printf("%d,%d %d,%d\n", operations[op][0], + operations[op][1], + operations[op][2], + operations[op][3]); + printf("xor(0x%x, 0x%x -> 0x%x, %d)\n", sptr, dptr, dptr, packetsize); */ + galois_region_xor(sptr, dptr, packetsize); + jerasure_total_xor_bytes += packetsize; + } else { +/* printf("memcpy(0x%x <- 0x%x)\n", dptr, sptr); */ + memcpy(dptr, sptr, packetsize); + jerasure_total_memcpy_bytes += packetsize; + } + } +} + +void jerasure_schedule_encode(int k, int m, int w, int **schedule, + char **data_ptrs, char **coding_ptrs, int size, int packetsize) +{ + char **ptr_copy; + int i, tdone; + + ptr_copy = talloc(char *, (k+m)); + for (i = 0; i < k; i++) ptr_copy[i] = data_ptrs[i]; + for (i = 0; i < m; i++) ptr_copy[i+k] = coding_ptrs[i]; + for (tdone = 0; tdone < size; tdone += packetsize*w) { + jerasure_do_scheduled_operations(ptr_copy, schedule, packetsize); + for (i = 0; i < k+m; i++) ptr_copy[i] += (packetsize*w); + } + free(ptr_copy); +} + +int **jerasure_dumb_bitmatrix_to_schedule(int k, int m, int w, int *bitmatrix) +{ + int **operations; + int op; + int index, optodo, i, j; + + operations = talloc(int *, k*m*w*w+1); + if (!operations) return NULL; + op = 0; + + index = 0; + for (i = 0; i < m*w; i++) { + optodo = 0; + for (j = 0; j < k*w; j++) { + if (bitmatrix[index]) { + operations[op] = talloc(int, 5); + if (!operations[op]) { + // -ENOMEM + goto error; + } + operations[op][4] = optodo; + operations[op][0] = j/w; + operations[op][1] = j%w; + operations[op][2] = k+i/w; + operations[op][3] = i%w; + optodo = 1; + op++; + + } + index++; + } + } + operations[op] = talloc(int, 5); + if (!operations[op]) { + // -ENOMEM + goto error; + } + operations[op][0] = -1; + return operations; + +error: + for (i = 0; i <= op; i++) { + free(operations[op]); + } + free(operations); + return NULL; +} + +int **jerasure_smart_bitmatrix_to_schedule(int k, int m, int w, int *bitmatrix) +{ + int **operations; + int op; + int i, j; + int *diff, *from, *b1, *flink, *blink; + int *ptr, no, row; + int optodo; + int bestrow = 0, bestdiff, top; + +/* printf("Scheduling:\n\n"); + jerasure_print_bitmatrix(bitmatrix, m*w, k*w, w); */ + + operations = talloc(int *, k*m*w*w+1); + if (!operations) return NULL; + op = 0; + + diff = talloc(int, m*w); + if (!diff) { + free(operations); + return NULL; + } + from = talloc(int, m*w); + if (!from) { + free(operations); + free(diff); + return NULL; + } + flink = talloc(int, m*w); + if (!flink) { + free(operations); + free(diff); + free(from); + return NULL; + } + blink = talloc(int, m*w); + if (!blink) { + free(operations); + free(diff); + free(from); + free(flink); + return NULL; + } + + ptr = bitmatrix; + + bestdiff = k*w+1; + top = 0; + for (i = 0; i < m*w; i++) { + no = 0; + for (j = 0; j < k*w; j++) { + no += *ptr; + ptr++; + } + diff[i] = no; + from[i] = -1; + flink[i] = i+1; + blink[i] = i-1; + if (no < bestdiff) { + bestdiff = no; + bestrow = i; + } + } + + flink[m*w-1] = -1; + + while (top != -1) { + row = bestrow; + /* printf("Doing row %d - %d from %d\n", row, diff[row], from[row]); */ + + if (blink[row] == -1) { + top = flink[row]; + if (top != -1) blink[top] = -1; + } else { + flink[blink[row]] = flink[row]; + if (flink[row] != -1) { + blink[flink[row]] = blink[row]; + } + } + + ptr = bitmatrix + row*k*w; + if (from[row] == -1) { + optodo = 0; + for (j = 0; j < k*w; j++) { + if (ptr[j]) { + operations[op] = talloc(int, 5); + if (!operations[op]) goto error; + operations[op][4] = optodo; + operations[op][0] = j/w; + operations[op][1] = j%w; + operations[op][2] = k+row/w; + operations[op][3] = row%w; + optodo = 1; + op++; + } + } + } else { + operations[op] = talloc(int, 5); + if (!operations[op]) goto error; + operations[op][4] = 0; + operations[op][0] = k+from[row]/w; + operations[op][1] = from[row]%w; + operations[op][2] = k+row/w; + operations[op][3] = row%w; + op++; + b1 = bitmatrix + from[row]*k*w; + for (j = 0; j < k*w; j++) { + if (ptr[j] ^ b1[j]) { + operations[op] = talloc(int, 5); + if (!operations[op]) goto error; + operations[op][4] = 1; + operations[op][0] = j/w; + operations[op][1] = j%w; + operations[op][2] = k+row/w; + operations[op][3] = row%w; + optodo = 1; + op++; + } + } + } + bestdiff = k*w+1; + for (i = top; i != -1; i = flink[i]) { + no = 1; + b1 = bitmatrix + i*k*w; + for (j = 0; j < k*w; j++) no += (ptr[j] ^ b1[j]); + if (no < diff[i]) { + from[i] = row; + diff[i] = no; + } + if (diff[i] < bestdiff) { + bestdiff = diff[i]; + bestrow = i; + } + } + } + + operations[op] = talloc(int, 5); + if (!operations[op]) goto error; + operations[op][0] = -1; + free(from); + free(diff); + free(blink); + free(flink); + + return operations; + +error: + for (i = 0; i <= op; i++) { + free(operations[op]); + } + free(operations); + free(from); + free(diff); + free(blink); + free(flink); + return NULL; +} + +void jerasure_bitmatrix_encode(int k, int m, int w, int *bitmatrix, + char **data_ptrs, char **coding_ptrs, int size, int packetsize) +{ + int i; + + if (packetsize%sizeof(long) != 0) { + fprintf(stderr, "jerasure_bitmatrix_encode - packetsize(%d) %c sizeof(long) != 0\n", packetsize, '%'); + assert(0); + } + if (size%(packetsize*w) != 0) { + fprintf(stderr, "jerasure_bitmatrix_encode - size(%d) %c (packetsize(%d)*w(%d))) != 0\n", + size, '%', packetsize, w); + assert(0); + } + + for (i = 0; i < m; i++) { + jerasure_bitmatrix_dotprod(k, w, bitmatrix+i*k*w*w, NULL, k+i, data_ptrs, coding_ptrs, size, packetsize); + } +} + +/* + * Exported function for use by autoconf to perform quick + * spot-check. + */ +int jerasure_autoconf_test() +{ + int x = galois_single_multiply(1, 2, 8); + if (x != 2) { + return -1; + } + return 0; +} + diff --git a/src/liberation.c b/src/liberation.c new file mode 100644 index 0000000..11a1c4f --- /dev/null +++ b/src/liberation.c @@ -0,0 +1,262 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank + */ + +#include +#include +#include + +#include "galois.h" +#include "jerasure.h" +#include "liberation.h" + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +int *liberation_coding_bitmatrix(int k, int w) +{ + int *matrix, i, j, index; + + if (k > w) return NULL; + matrix = talloc(int, 2*k*w*w); + if (matrix == NULL) return NULL; + bzero(matrix, sizeof(int)*2*k*w*w); + + /* Set up identity matrices */ + + for(i = 0; i < w; i++) { + index = i*k*w+i; + for (j = 0; j < k; j++) { + matrix[index] = 1; + index += w; + } + } + + /* Set up liberation matrices */ + + for (j = 0; j < k; j++) { + index = k*w*w+j*w; + for (i = 0; i < w; i++) { + matrix[index+(j+i)%w] = 1; + index += (k*w); + } + if (j > 0) { + i = (j*((w-1)/2))%w; + matrix[k*w*w+j*w+i*k*w+(i+j-1)%w] = 1; + } + } + return matrix; +} + + +int *liber8tion_coding_bitmatrix(int k) +{ + int *matrix, i, j, index; + int w; + + w = 8; + if (k > w) return NULL; + matrix = talloc(int, 2*k*w*w); + if (matrix == NULL) return NULL; + bzero(matrix, sizeof(int)*2*k*w*w); + + /* Set up identity matrices */ + + for(i = 0; i < w; i++) { + index = i*k*w+i; + for (j = 0; j < k; j++) { + matrix[index] = 1; + index += w; + } + } + + /* Set up liber8tion matrices */ + + index = k*w*w; + + if (k == 0) return matrix; + matrix[index+0*k*w+0*w+0] = 1; + matrix[index+1*k*w+0*w+1] = 1; + matrix[index+2*k*w+0*w+2] = 1; + matrix[index+3*k*w+0*w+3] = 1; + matrix[index+4*k*w+0*w+4] = 1; + matrix[index+5*k*w+0*w+5] = 1; + matrix[index+6*k*w+0*w+6] = 1; + matrix[index+7*k*w+0*w+7] = 1; + + if (k == 1) return matrix; + matrix[index+0*k*w+1*w+7] = 1; + matrix[index+1*k*w+1*w+3] = 1; + matrix[index+2*k*w+1*w+0] = 1; + matrix[index+3*k*w+1*w+2] = 1; + matrix[index+4*k*w+1*w+6] = 1; + matrix[index+5*k*w+1*w+1] = 1; + matrix[index+6*k*w+1*w+5] = 1; + matrix[index+7*k*w+1*w+4] = 1; + matrix[index+4*k*w+1*w+7] = 1; + + if (k == 2) return matrix; + matrix[index+0*k*w+2*w+6] = 1; + matrix[index+1*k*w+2*w+2] = 1; + matrix[index+2*k*w+2*w+4] = 1; + matrix[index+3*k*w+2*w+0] = 1; + matrix[index+4*k*w+2*w+7] = 1; + matrix[index+5*k*w+2*w+3] = 1; + matrix[index+6*k*w+2*w+1] = 1; + matrix[index+7*k*w+2*w+5] = 1; + matrix[index+1*k*w+2*w+3] = 1; + + if (k == 3) return matrix; + matrix[index+0*k*w+3*w+2] = 1; + matrix[index+1*k*w+3*w+5] = 1; + matrix[index+2*k*w+3*w+7] = 1; + matrix[index+3*k*w+3*w+6] = 1; + matrix[index+4*k*w+3*w+0] = 1; + matrix[index+5*k*w+3*w+3] = 1; + matrix[index+6*k*w+3*w+4] = 1; + matrix[index+7*k*w+3*w+1] = 1; + matrix[index+5*k*w+3*w+4] = 1; + + if (k == 4) return matrix; + matrix[index+0*k*w+4*w+5] = 1; + matrix[index+1*k*w+4*w+6] = 1; + matrix[index+2*k*w+4*w+1] = 1; + matrix[index+3*k*w+4*w+7] = 1; + matrix[index+4*k*w+4*w+2] = 1; + matrix[index+5*k*w+4*w+4] = 1; + matrix[index+6*k*w+4*w+3] = 1; + matrix[index+7*k*w+4*w+0] = 1; + matrix[index+2*k*w+4*w+0] = 1; + + if (k == 5) return matrix; + matrix[index+0*k*w+5*w+1] = 1; + matrix[index+1*k*w+5*w+2] = 1; + matrix[index+2*k*w+5*w+3] = 1; + matrix[index+3*k*w+5*w+4] = 1; + matrix[index+4*k*w+5*w+5] = 1; + matrix[index+5*k*w+5*w+6] = 1; + matrix[index+6*k*w+5*w+7] = 1; + matrix[index+7*k*w+5*w+0] = 1; + matrix[index+7*k*w+5*w+2] = 1; + + if (k == 6) return matrix; + matrix[index+0*k*w+6*w+3] = 1; + matrix[index+1*k*w+6*w+0] = 1; + matrix[index+2*k*w+6*w+6] = 1; + matrix[index+3*k*w+6*w+5] = 1; + matrix[index+4*k*w+6*w+1] = 1; + matrix[index+5*k*w+6*w+7] = 1; + matrix[index+6*k*w+6*w+4] = 1; + matrix[index+7*k*w+6*w+2] = 1; + matrix[index+6*k*w+6*w+5] = 1; + + if (k == 7) return matrix; + matrix[index+0*k*w+7*w+4] = 1; + matrix[index+1*k*w+7*w+7] = 1; + matrix[index+2*k*w+7*w+1] = 1; + matrix[index+3*k*w+7*w+5] = 1; + matrix[index+4*k*w+7*w+3] = 1; + matrix[index+5*k*w+7*w+2] = 1; + matrix[index+6*k*w+7*w+0] = 1; + matrix[index+7*k*w+7*w+6] = 1; + matrix[index+3*k*w+7*w+1] = 1; + + return matrix; +} + +int *blaum_roth_coding_bitmatrix(int k, int w) +{ + int *matrix, i, j, index, l, m, p; + + if (k > w) return NULL ; + + matrix = talloc(int, 2*k*w*w); + if (matrix == NULL) return NULL; + bzero(matrix, sizeof(int)*2*k*w*w); + + /* Set up identity matrices */ + + for(i = 0; i < w; i++) { + index = i*k*w+i; + for (j = 0; j < k; j++) { + matrix[index] = 1; + index += w; + } + } + + /* Set up blaum_roth matrices -- Ignore identity */ + + p = w+1; + for (j = 0; j < k; j++) { + index = k*w*w+j*w; + if (j == 0) { + for (l = 0; l < w; l++) { + matrix[index+l] = 1; + index += k*w; + } + } else { + i = j; + for (l = 1; l <= w; l++) { + if (l != p-i) { + m = l+i; + if (m >= p) m -= p; + m--; + matrix[index+m] = 1; + } else { + matrix[index+i-1] = 1; + if (i%2 == 0) { + m = i/2; + } else { + m = (p/2) + 1 + (i/2); + } + m--; + matrix[index+m] = 1; + } + index += k*w; + } + } + } + + return matrix; +} diff --git a/src/reed_sol.c b/src/reed_sol.c new file mode 100644 index 0000000..72cbff8 --- /dev/null +++ b/src/reed_sol.c @@ -0,0 +1,302 @@ +/* * + * Copyright (c) 2014, James S. Plank and Kevin Greenan + * All rights reserved. + * + * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure + * Coding Techniques + * + * Revision 2.0: Galois Field backend now links to GF-Complete + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of the University of Tennessee nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Jerasure's authors: + + Revision 2.x - 2014: James S. Plank and Kevin M. Greenan + Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman. + Revision 1.0 - 2007: James S. Plank + */ + +#include +#include +#include +#include + +#include +#include "galois.h" +#include "jerasure.h" +#include "reed_sol.h" + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +int *reed_sol_r6_coding_matrix(int k, int w) +{ + int *matrix; + int i, tmp; + + if (w != 8 && w != 16 && w != 32) return NULL; + + matrix = talloc(int, 2*k); + if (matrix == NULL) return NULL; + + for (i = 0; i < k; i++) matrix[i] = 1; + matrix[k] = 1; + tmp = 1; + for (i = 1; i < k; i++) { + tmp = galois_single_multiply(tmp, 2, w); + matrix[k+i] = tmp; + } + return matrix; +} + +int *reed_sol_vandermonde_coding_matrix(int k, int m, int w) +{ + int i, j; + int *vdm, *dist; + + vdm = reed_sol_big_vandermonde_distribution_matrix(k+m, k, w); + if (vdm == NULL) return NULL; + dist = talloc(int, m*k); + if (dist == NULL) { + free(vdm); + return NULL; + } + + i = k*k; + for (j = 0; j < m*k; j++) { + dist[j] = vdm[i]; + i++; + } + free(vdm); + return dist; +} + +static int prim08 = -1; +static gf_t GF08; + +void reed_sol_galois_w08_region_multby_2(char *region, int nbytes) +{ + if (prim08 == -1) { + prim08 = galois_single_multiply((1 << 7), 2, 8); + if (!gf_init_hard(&GF08, 8, GF_MULT_BYTWO_b, GF_REGION_DEFAULT, GF_DIVIDE_DEFAULT, + prim08, 0, 0, NULL, NULL)) { + fprintf(stderr, "Error: Can't initialize the GF for reed_sol_galois_w08_region_multby_2\n"); + assert(0); + } + } + GF08.multiply_region.w32(&GF08, region, region, 2, nbytes, 0); +} + +static int prim16 = -1; +static gf_t GF16; + +void reed_sol_galois_w16_region_multby_2(char *region, int nbytes) +{ + if (prim16 == -1) { + prim16 = galois_single_multiply((1 << 15), 2, 16); + if (!gf_init_hard(&GF16, 16, GF_MULT_BYTWO_b, GF_REGION_DEFAULT, GF_DIVIDE_DEFAULT, + prim16, 0, 0, NULL, NULL)) { + fprintf(stderr, "Error: Can't initialize the GF for reed_sol_galois_w16_region_multby_2\n"); + assert(0); + } + } + GF16.multiply_region.w32(&GF16, region, region, 2, nbytes, 0); +} + +static int prim32 = -1; +static gf_t GF32; + +void reed_sol_galois_w32_region_multby_2(char *region, int nbytes) +{ + if (prim32 == -1) { + prim32 = galois_single_multiply(((gf_val_32_t)1 << 31), 2, 32); + if (!gf_init_hard(&GF32, 32, GF_MULT_BYTWO_b, GF_REGION_DEFAULT, GF_DIVIDE_DEFAULT, + prim32, 0, 0, NULL, NULL)) { + fprintf(stderr, "Error: Can't initialize the GF for reed_sol_galois_w32_region_multby_2\n"); + assert(0); + } + } + GF32.multiply_region.w32(&GF32, region, region, 2, nbytes, 0); +} + +int reed_sol_r6_encode(int k, int w, char **data_ptrs, char **coding_ptrs, int size) +{ + int i; + + /* First, put the XOR into coding region 0 */ + + memcpy(coding_ptrs[0], data_ptrs[0], size); + + for (i = 1; i < k; i++) galois_region_xor(data_ptrs[i], coding_ptrs[0], size); + + /* Next, put the sum of (2^j)*Dj into coding region 1 */ + + memcpy(coding_ptrs[1], data_ptrs[k-1], size); + + for (i = k-2; i >= 0; i--) { + switch (w) { + case 8: reed_sol_galois_w08_region_multby_2(coding_ptrs[1], size); break; + case 16: reed_sol_galois_w16_region_multby_2(coding_ptrs[1], size); break; + case 32: reed_sol_galois_w32_region_multby_2(coding_ptrs[1], size); break; + default: return 0; + } + + galois_region_xor(data_ptrs[i], coding_ptrs[1], size); + } + return 1; +} + +int *reed_sol_extended_vandermonde_matrix(int rows, int cols, int w) +{ + int *vdm; + int i, j, k; + + if (w < 30 && (1 << w) < rows) return NULL; + if (w < 30 && (1 << w) < cols) return NULL; + + vdm = talloc(int, rows*cols); + if (vdm == NULL) { return NULL; } + + vdm[0] = 1; + for (j = 1; j < cols; j++) vdm[j] = 0; + if (rows == 1) return vdm; + + i=(rows-1)*cols; + for (j = 0; j < cols-1; j++) vdm[i+j] = 0; + vdm[i+j] = 1; + if (rows == 2) return vdm; + + for (i = 1; i < rows-1; i++) { + k = 1; + for (j = 0; j < cols; j++) { + vdm[i*cols+j] = k; + k = galois_single_multiply(k, i, w); + } + } + return vdm; +} + +int *reed_sol_big_vandermonde_distribution_matrix(int rows, int cols, int w) +{ + int *dist; + int i, j, k; + int sindex, srindex, siindex, tmp; + + if (cols >= rows) return NULL; + + dist = reed_sol_extended_vandermonde_matrix(rows, cols, w); + if (dist == NULL) return NULL; + + sindex = 0; + for (i = 1; i < cols; i++) { + sindex += cols; + + /* Find an appropriate row -- where i,i != 0 */ + srindex = sindex+i; + for (j = i; j < rows && dist[srindex] == 0; j++) srindex += cols; + if (j >= rows) { /* This should never happen if rows/w are correct */ + fprintf(stderr, "reed_sol_big_vandermonde_distribution_matrix(%d,%d,%d) - couldn't make matrix\n", + rows, cols, w); + assert(0); + } + + /* If necessary, swap rows */ + if (j != i) { + srindex -= i; + for (k = 0; k < cols; k++) { + tmp = dist[srindex+k]; + dist[srindex+k] = dist[sindex+k]; + dist[sindex+k] = tmp; + } + } + + /* If Element i,i is not equal to 1, multiply the column by 1/i */ + + if (dist[sindex+i] != 1) { + tmp = galois_single_divide(1, dist[sindex+i], w); + srindex = i; + for (j = 0; j < rows; j++) { + dist[srindex] = galois_single_multiply(tmp, dist[srindex], w); + srindex += cols; + } + } + + /* Now, for each element in row i that is not in column 1, you need + to make it zero. Suppose that this is column j, and the element + at i,j = e. Then you want to replace all of column j with + (col-j + col-i*e). Note, that in row i, col-i = 1 and col-j = e. + So (e + 1e) = 0, which is indeed what we want. */ + + for (j = 0; j < cols; j++) { + tmp = dist[sindex+j]; + if (j != i && tmp != 0) { + srindex = j; + siindex = i; + for (k = 0; k < rows; k++) { + dist[srindex] = dist[srindex] ^ galois_single_multiply(tmp, dist[siindex], w); + srindex += cols; + siindex += cols; + } + } + } + } + /* We desire to have row k be all ones. To do that, multiply + the entire column j by 1/dist[k,j]. Then row j by 1/dist[j,j]. */ + + sindex = cols*cols; + for (j = 0; j < cols; j++) { + tmp = dist[sindex]; + if (tmp != 1) { + tmp = galois_single_divide(1, tmp, w); + srindex = sindex; + for (i = cols; i < rows; i++) { + dist[srindex] = galois_single_multiply(tmp, dist[srindex], w); + srindex += cols; + } + } + sindex++; + } + + /* Finally, we'd like the first column of each row to be all ones. To + do that, we multiply the row by the inverse of the first element. */ + + sindex = cols*(cols+1); + for (i = cols+1; i < rows; i++) { + tmp = dist[sindex]; + if (tmp != 1) { + tmp = galois_single_divide(1, tmp, w); + for (j = 0; j < cols; j++) dist[sindex+j] = galois_single_multiply(dist[sindex+j], tmp, w); + } + sindex += cols; + } + + return dist; +} + diff --git a/src/timing.c b/src/timing.c new file mode 100644 index 0000000..315870a --- /dev/null +++ b/src/timing.c @@ -0,0 +1,63 @@ +// Timing measurement utilities implementation. + +#include "timing.h" +#include + +void +timing_set( + struct timing * t) +{ +#ifdef USE_CLOCK + t->clock = clock(); +#else + gettimeofday(&t->tv, NULL); +#endif +} + +double +timing_get( + struct timing * t) +{ +#ifdef USE_CLOCK + // The clock_t type is an "arithmetic type", which could be + // integral, double, long double, or others. + // + // Add 0.0 to make it a double or long double, then divide (in + // double or long double), then convert to double for our purposes. + return (double) ((t->clock + 0.0) / CLOCKS_PER_SEC); +#else + return (double) t->tv.tv_sec + ((double) t->tv.tv_usec) / 1000000.0; +#endif +} + +double +timing_now() +{ +#ifdef USE_CLOCK + return (double) ((clock() + 0.0) / CLOCKS_PER_SEC); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return (double) tv.tv_sec + ((double) tv.tv_usec) / 1000000.0; +#endif +} + +double +timing_delta( + struct timing * t1, + struct timing * t2) +{ +#ifdef USE_CLOCK + // The clock_t type is an "arithmetic type", which could be + // integral, double, long double, or others. + // + // Subtract first, resulting in another clock_t, then add 0.0 to + // make it a double or long double, then divide (in double or long + // double), then convert to double for our purposes. + return (double) (((t2->clock - t1->clock) + 0.0) / CLOCKS_PER_SEC); +#else + double const d2 = (double) t2->tv.tv_sec + ((double) t2->tv.tv_usec) / 1000000.0; + double const d1 = (double) t1->tv.tv_sec + ((double) t1->tv.tv_usec) / 1000000.0; + return d2 - d1; +#endif +} -- 2.39.5