]> git.rkrishnan.org Git - tahoe-lafs/zfec.git/blobdiff - zfec/zfec/fec.c
narrow types of k and m from unsigned to unsigned short
[tahoe-lafs/zfec.git] / zfec / zfec / fec.c
index 4d64e29628d22e6ec470fa51560ef58ee453aab6..637498d02aa01244f175f41eedc621f8ad4fc650 100644 (file)
@@ -2,24 +2,13 @@
  * zfec -- fast forward error correction library with Python interface
  */
 
+#include "fec.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 
-#include "fec.h"
-
-
-/*
- * If you get a error returned (negative value) from a fec_* function, 
- * look in here for the error message.
- */
-
-#define FEC_ERROR_SIZE 1025
-char fec_error[FEC_ERROR_SIZE+1];
-
-#define ERR(...) (snprintf(fec_error, FEC_ERROR_SIZE, __VA_ARGS__))
-
 /*
  * Primitive polynomials - see Lin & Costello, Appendix A,
  * and  Lee & Messerschmitt, p. 453.
@@ -45,7 +34,7 @@ static gf inverse[256]; /* inverse of field elem.               */
  * modnn(x) computes x % GF_SIZE, where GF_SIZE is 2**GF_BITS - 1,
  * without a slow divide.
  */
-static inline gf
+static gf
 modnn(int x) {
     while (x >= 255) {
         x -= 255;
@@ -71,6 +60,7 @@ static gf gf_mul_table[256][256];
 #define gf_mul(x,y) gf_mul_table[x][y]
 
 #define USE_GF_MULC register gf * __gf_mulc_
+
 #define GF_MULC0(c) __gf_mulc_ = gf_mul_table[c]
 #define GF_ADDMULC(dst, x) dst ^= __gf_mulc_[x]
 
@@ -95,22 +85,8 @@ _init_mul_table(void) {
       gf_mul_table[0][j] = gf_mul_table[j][0] = 0;
 }
 
-/*
- * i use malloc so many times, it is easier to put checks all in
- * one place.
- */
-static void *
-my_malloc (int sz, char *err_string) {
-    void *p = malloc (sz);
-    if (p == NULL) {
-        ERR("Malloc failure allocating %s\n", err_string);
-        exit (1);
-    }
-    return p;
-}
-
 #define NEW_GF_MATRIX(rows, cols) \
-    (gf*)my_malloc(rows * cols, " ## __LINE__ ## " )
+    (gf*)malloc(rows * cols)
 
 /*
  * initialize the data structures used for computations in GF.
@@ -259,11 +235,10 @@ _invert_mat(gf* src, unsigned k) {
     unsigned icol = 0;
     unsigned row, col, i, ix;
 
-    unsigned* indxc = (unsigned*) my_malloc (k * sizeof(unsigned), "indxc");
-    unsigned* indxr = (unsigned*) my_malloc (k * sizeof(unsigned), "indxr");
-    unsigned* ipiv = (unsigned*) my_malloc (k * sizeof(unsigned), "ipiv");
+    unsigned* indxc = (unsigned*) malloc (k * sizeof(unsigned));
+    unsigned* indxr = (unsigned*) malloc (k * sizeof(unsigned));
+    unsigned* ipiv = (unsigned*) malloc (k * sizeof(unsigned));
     gf *id_row = NEW_GF_MATRIX (1, k);
-    gf *temp_row = NEW_GF_MATRIX (1, k);
 
     memset (id_row, '\0', k * sizeof (gf));
     /*
@@ -292,10 +267,8 @@ _invert_mat(gf* src, unsigned k) {
                             icol = ix;
                             goto found_piv;
                         }
-                    } else if (ipiv[ix] > 1) {
-                        ERR("singular matrix");
-                        goto fail;
-                    }
+                    } else
+                        assert (ipiv[ix] <= 1);
                 }
             }
         }
@@ -313,10 +286,7 @@ _invert_mat(gf* src, unsigned k) {
         indxc[col] = icol;
         pivot_row = &src[icol * k];
         c = pivot_row[icol];
-        if (c == 0) {
-            ERR("singular matrix 2");
-            goto fail;
-        }
+        assert (c != 0);
         if (c != 1) {                       /* otherwhise this is a NOP */
             /*
              * this is done often , but optimizing is not so
@@ -350,13 +320,6 @@ _invert_mat(gf* src, unsigned k) {
         if (indxr[col-1] != indxc[col-1])
             for (row = 0; row < k; row++)
                 SWAP (src[row * k + indxr[col-1]], src[row * k + indxc[col-1]], gf);
-  fail:
-    free (indxc);
-    free (indxr);
-    free (ipiv);
-    free (id_row);
-    free (temp_row);
-    return;
 }
 
 /*
@@ -443,28 +406,22 @@ init_fec (void) {
 
 void
 fec_free (fec_t *p) {
-    if (p == NULL ||
-        p->magic != (((FEC_MAGIC ^ p->k) ^ p->n) ^ (unsigned long) (p->enc_matrix))) {
-        ERR("bad parameters to fec_free");
-        return;
-    }
+    assert (p != NULL && p->magic == (((FEC_MAGIC ^ p->k) ^ p->n) ^ (unsigned long) (p->enc_matrix)));
     free (p->enc_matrix);
     free (p);
 }
 
 fec_t *
-fec_new(unsigned k, unsigned n) {
+fec_new(unsigned short k, unsigned short n) {
     unsigned row, col;
     gf *p, *tmp_m;
 
     fec_t *retval;
 
-    fec_error[FEC_ERROR_SIZE] = '\0';
-
     if (fec_initialized == 0)
         init_fec ();
 
-    retval = (fec_t *) my_malloc (sizeof (fec_t), "new_code");
+    retval = (fec_t *) malloc (sizeof (fec_t));
     retval->k = k;
     retval->n = n;
     retval->enc_matrix = NEW_GF_MATRIX (n, k);
@@ -499,19 +456,29 @@ fec_new(unsigned k, unsigned n) {
     return retval;
 }
 
+/* To make sure that we stay within cache in the inner loops of fec_encode().  (It would
+   probably help to also do this for fec_decode(). */
+#ifndef STRIDE
+#define STRIDE 8192
+#endif
+
 void
 fec_encode(const fec_t* code, const gf*restrict const*restrict const src, gf*restrict const*restrict const fecs, const unsigned*restrict const block_nums, size_t num_block_nums, size_t sz) {
     unsigned char i, j;
+    size_t k;
     unsigned fecnum;
-    gf* p;
-
-    for (i=0; i<num_block_nums; i++) {
-        fecnum=block_nums[i];
-        assert (fecnum >= code->k);
-        memset(fecs[i], 0, sz);
-        p = &(code->enc_matrix[fecnum * code->k]);
-        for (j = 0; j < code->k; j++)
-            addmul(fecs[i], src[j], p[j], sz);
+    const gf* p;
+
+    for (k = 0; k < sz; k += STRIDE) {
+        size_t stride = ((sz-k) < STRIDE)?(sz-k):STRIDE;
+        for (i=0; i<num_block_nums; i++) {
+            fecnum=block_nums[i];
+            assert (fecnum >= code->k);
+            memset(fecs[i]+k, 0, stride);
+            p = &(code->enc_matrix[fecnum * code->k]);
+            for (j = 0; j < code->k; j++)
+                addmul(fecs[i]+k, src[j]+k, p[j], stride);
+        }
     }
 }
 
@@ -537,14 +504,17 @@ build_decode_matrix_into_space(const fec_t*restrict const code, const unsigned*c
 
 void
 fec_decode(const fec_t* code, const gf*restrict const*restrict const inpkts, gf*restrict const*restrict const outpkts, const unsigned*restrict const index, size_t sz) {
-    gf m_dec[code->k * code->k];
+    gf* m_dec = (gf*)alloca(code->k * code->k);
+    unsigned char outix=0;
+    unsigned char row=0;
+    unsigned char col=0;
     build_decode_matrix_into_space(code, index, code->k, m_dec);
 
-    unsigned char outix=0;
-    for (unsigned char row=0; row<code->k; row++) {
+    for (row=0; row<code->k; row++) {
+        assert ((index[row] >= code->k) || (index[row] == row)); /* If the block whose number is i is present, then it is required to be in the i'th element. */
         if (index[row] >= code->k) {
             memset(outpkts[outix], 0, sz);
-            for (unsigned char col=0; col < code->k; col++)
+            for (col=0; col < code->k; col++)
                 addmul(outpkts[outix], inpkts[col], m_dec[row * code->k + col], sz);
             outix++;
         }
@@ -553,38 +523,20 @@ fec_decode(const fec_t* code, const gf*restrict const*restrict const inpkts, gf*
 
 /**
  * zfec -- fast forward error correction library with Python interface
- *
+ * 
  * Copyright (C) 2007 Allmydata, Inc.
  * Author: Zooko Wilcox-O'Hearn
- * mailto:zooko@zooko.com
- *
+ * 
  * This file is part of zfec.
  * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.  This license also comes with the added permission that,
- * if you become obligated to release a derived work under this licence (as
- * per section 2.b of the GPL), you may delay the fulfillment of this
- * obligation for up to 12 months.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * See README.txt for licensing information.
  */
 
 /*
- * Much of this work is derived from the "fec" software by Luigi Rizzo, et
- * al., the copyright notice and licence terms of which are included below
- * for reference.
- * fec.c -- forward error correction based on Vandermonde matrices
- * 980624
- * (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it)
+ * This work is derived from the "fec" software by Luigi Rizzo, et al., the
+ * copyright notice and licence terms of which are included below for reference.
+ * fec.c -- forward error correction based on Vandermonde matrices 980624 (C)
+ * 1997-98 Luigi Rizzo (luigi@iet.unipi.it)
  *
  * Portions derived from code by Phil Karn (karn@ka9q.ampr.org),
  * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari
@@ -618,4 +570,3 @@ fec_decode(const fec_t* code, const gf*restrict const*restrict const inpkts, gf*
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  */
-