diff --git a/Examples/makefile b/Examples/makefile index c01977f..7131efc 100755 --- a/Examples/makefile +++ b/Examples/makefile @@ -42,7 +42,10 @@ # WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. - +PREFIX=/usr/local +BINDIR=${PREFIX}/bin +LIBDIR=${PREFIX}/lib +INCDIR=${PREFIX}/include CC = gcc CFLAGS = -O2 -I$(HOME)/include @@ -106,81 +109,81 @@ galois.h: ../galois.h galois.c: ../galois.c rm -f galois.c ; cp ../galois.c . ; chmod 0444 galois.c -galois.o: galois.h +galois.o ${LIBDIR}/gf_complete.a: galois.h jerasure.o: jerasure.h galois.h jerasure_01.o: galois.h jerasure.h -jerasure_01: jerasure_01.o galois.o jerasure.o - $(CC) $(CFLAGS) -o jerasure_01 jerasure_01.o jerasure.o galois.o +jerasure_01: jerasure_01.o galois.o ${LIBDIR}/gf_complete.a jerasure.o + $(CC) $(CFLAGS) -o jerasure_01 jerasure_01.o jerasure.o galois.o ${LIBDIR}/gf_complete.a jerasure_02.o: galois.h jerasure.h -jerasure_02: jerasure_02.o galois.o jerasure.o - $(CC) $(CFLAGS) -o jerasure_02 jerasure_02.o jerasure.o galois.o +jerasure_02: jerasure_02.o galois.o ${LIBDIR}/gf_complete.a jerasure.o + $(CC) $(CFLAGS) -o jerasure_02 jerasure_02.o jerasure.o galois.o ${LIBDIR}/gf_complete.a jerasure_03.o: galois.h jerasure.h -jerasure_03: jerasure_03.o galois.o jerasure.o - $(CC) $(CFLAGS) -o jerasure_03 jerasure_03.o jerasure.o galois.o +jerasure_03: jerasure_03.o galois.o ${LIBDIR}/gf_complete.a jerasure.o + $(CC) $(CFLAGS) -o jerasure_03 jerasure_03.o jerasure.o galois.o ${LIBDIR}/gf_complete.a jerasure_04.o: galois.h jerasure.h -jerasure_04: jerasure_04.o galois.o jerasure.o - $(CC) $(CFLAGS) -o jerasure_04 jerasure_04.o jerasure.o galois.o +jerasure_04: jerasure_04.o galois.o ${LIBDIR}/gf_complete.a jerasure.o + $(CC) $(CFLAGS) -o jerasure_04 jerasure_04.o jerasure.o galois.o ${LIBDIR}/gf_complete.a jerasure_05.o: galois.h jerasure.h -jerasure_05: jerasure_05.o galois.o jerasure.o - $(CC) $(CFLAGS) -o jerasure_05 jerasure_05.o jerasure.o galois.o +jerasure_05: jerasure_05.o galois.o ${LIBDIR}/gf_complete.a jerasure.o + $(CC) $(CFLAGS) -o jerasure_05 jerasure_05.o jerasure.o galois.o ${LIBDIR}/gf_complete.a jerasure_06.o: galois.h jerasure.h -jerasure_06: jerasure_06.o galois.o jerasure.o - $(CC) $(CFLAGS) -o jerasure_06 jerasure_06.o jerasure.o galois.o +jerasure_06: jerasure_06.o galois.o ${LIBDIR}/gf_complete.a jerasure.o + $(CC) $(CFLAGS) -o jerasure_06 jerasure_06.o jerasure.o galois.o ${LIBDIR}/gf_complete.a jerasure_07.o: galois.h jerasure.h -jerasure_07: jerasure_07.o galois.o jerasure.o - $(CC) $(CFLAGS) -o jerasure_07 jerasure_07.o jerasure.o galois.o +jerasure_07: jerasure_07.o galois.o ${LIBDIR}/gf_complete.a jerasure.o + $(CC) $(CFLAGS) -o jerasure_07 jerasure_07.o jerasure.o galois.o ${LIBDIR}/gf_complete.a jerasure_08.o: galois.h jerasure.h -jerasure_08: jerasure_08.o galois.o jerasure.o - $(CC) $(CFLAGS) -o jerasure_08 jerasure_08.o jerasure.o galois.o +jerasure_08: jerasure_08.o galois.o ${LIBDIR}/gf_complete.a jerasure.o + $(CC) $(CFLAGS) -o jerasure_08 jerasure_08.o jerasure.o galois.o ${LIBDIR}/gf_complete.a reed_sol_01.o: galois.h reed_sol.h jerasure.h -reed_sol_01: reed_sol_01.o galois.o jerasure.o reed_sol.o - $(CC) $(CFLAGS) -o reed_sol_01 reed_sol_01.o reed_sol.o jerasure.o galois.o +reed_sol_01: reed_sol_01.o galois.o ${LIBDIR}/gf_complete.a jerasure.o reed_sol.o + $(CC) $(CFLAGS) -o reed_sol_01 reed_sol_01.o reed_sol.o jerasure.o galois.o ${LIBDIR}/gf_complete.a reed_sol_02.o: galois.h reed_sol.h jerasure.h -reed_sol_02: reed_sol_02.o galois.o jerasure.o reed_sol.o - $(CC) $(CFLAGS) -o reed_sol_02 reed_sol_02.o reed_sol.o jerasure.o galois.o +reed_sol_02: reed_sol_02.o galois.o ${LIBDIR}/gf_complete.a jerasure.o reed_sol.o + $(CC) $(CFLAGS) -o reed_sol_02 reed_sol_02.o reed_sol.o jerasure.o galois.o ${LIBDIR}/gf_complete.a reed_sol_03.o: galois.h reed_sol.h jerasure.h -reed_sol_03: reed_sol_03.o galois.o jerasure.o reed_sol.o - $(CC) $(CFLAGS) -o reed_sol_03 reed_sol_03.o reed_sol.o jerasure.o galois.o +reed_sol_03: reed_sol_03.o galois.o ${LIBDIR}/gf_complete.a jerasure.o reed_sol.o + $(CC) $(CFLAGS) -o reed_sol_03 reed_sol_03.o reed_sol.o jerasure.o galois.o ${LIBDIR}/gf_complete.a reed_sol_04.o: galois.h reed_sol.h jerasure.h -reed_sol_04: reed_sol_04.o galois.o jerasure.o reed_sol.o - $(CC) $(CFLAGS) -o reed_sol_04 reed_sol_04.o reed_sol.o jerasure.o galois.o +reed_sol_04: reed_sol_04.o galois.o ${LIBDIR}/gf_complete.a jerasure.o reed_sol.o + $(CC) $(CFLAGS) -o reed_sol_04 reed_sol_04.o reed_sol.o jerasure.o galois.o ${LIBDIR}/gf_complete.a cauchy_01.o: galois.h cauchy.h jerasure.h -cauchy_01: cauchy_01.o galois.o jerasure.o cauchy.o - $(CC) $(CFLAGS) -o cauchy_01 cauchy_01.o cauchy.o jerasure.o galois.o +cauchy_01: cauchy_01.o galois.o ${LIBDIR}/gf_complete.a jerasure.o cauchy.o + $(CC) $(CFLAGS) -o cauchy_01 cauchy_01.o cauchy.o jerasure.o galois.o ${LIBDIR}/gf_complete.a cauchy_02.o: galois.h cauchy.h jerasure.h -cauchy_02: cauchy_02.o galois.o jerasure.o cauchy.o - $(CC) $(CFLAGS) -o cauchy_02 cauchy_02.o cauchy.o jerasure.o galois.o +cauchy_02: cauchy_02.o galois.o ${LIBDIR}/gf_complete.a jerasure.o cauchy.o + $(CC) $(CFLAGS) -o cauchy_02 cauchy_02.o cauchy.o jerasure.o galois.o ${LIBDIR}/gf_complete.a cauchy_03.o: galois.h cauchy.h jerasure.h -cauchy_03: cauchy_03.o galois.o jerasure.o cauchy.o - $(CC) $(CFLAGS) -o cauchy_03 cauchy_03.o cauchy.o jerasure.o galois.o +cauchy_03: cauchy_03.o galois.o ${LIBDIR}/gf_complete.a jerasure.o cauchy.o + $(CC) $(CFLAGS) -o cauchy_03 cauchy_03.o cauchy.o jerasure.o galois.o ${LIBDIR}/gf_complete.a cauchy_04.o: galois.h cauchy.h jerasure.h -cauchy_04: cauchy_04.o galois.o jerasure.o cauchy.o - $(CC) $(CFLAGS) -o cauchy_04 cauchy_04.o cauchy.o jerasure.o galois.o +cauchy_04: cauchy_04.o galois.o ${LIBDIR}/gf_complete.a jerasure.o cauchy.o + $(CC) $(CFLAGS) -o cauchy_04 cauchy_04.o cauchy.o jerasure.o galois.o ${LIBDIR}/gf_complete.a liberation_01.o: galois.h liberation.h jerasure.h -liberation_01: liberation_01.o galois.o jerasure.o liberation.o - $(CC) $(CFLAGS) -o liberation_01 liberation_01.o liberation.o jerasure.o galois.o +liberation_01: liberation_01.o galois.o ${LIBDIR}/gf_complete.a jerasure.o liberation.o + $(CC) $(CFLAGS) -o liberation_01 liberation_01.o liberation.o jerasure.o galois.o ${LIBDIR}/gf_complete.a encoder.o: galois.h liberation.h jerasure.h reed_sol.h cauchy.h -encoder: encoder.o galois.o jerasure.o liberation.o reed_sol.o cauchy.o - $(CC) $(CFLAGS) -o encoder encoder.o liberation.o jerasure.o galois.o reed_sol.o cauchy.o +encoder: encoder.o galois.o ${LIBDIR}/gf_complete.a jerasure.o liberation.o reed_sol.o cauchy.o + $(CC) $(CFLAGS) -o encoder encoder.o liberation.o jerasure.o galois.o ${LIBDIR}/gf_complete.a reed_sol.o cauchy.o decoder.o: galois.h liberation.h jerasure.h reed_sol.h cauchy.h -decoder: decoder.o galois.o jerasure.o liberation.o reed_sol.o cauchy.o - $(CC) $(CFLAGS) -o decoder decoder.o liberation.o jerasure.o galois.o reed_sol.o cauchy.o +decoder: decoder.o galois.o ${LIBDIR}/gf_complete.a jerasure.o liberation.o reed_sol.o cauchy.o + $(CC) $(CFLAGS) -o decoder decoder.o liberation.o jerasure.o galois.o ${LIBDIR}/gf_complete.a reed_sol.o cauchy.o diff --git a/Test/makefile b/Test/makefile new file mode 100755 index 0000000..8ead2d1 --- /dev/null +++ b/Test/makefile @@ -0,0 +1,101 @@ +# Examples/makefile +# Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques +# +# Revision 1.2A +# May 24, 2011 +# +# James S. Plank +# Department of Electrical Engineering and Computer Science +# University of Tennessee +# Knoxville, TN 37996 +# plank@cs.utk.edu +# +# Copyright (c) 2011, James S. Plank +# All rights reserved. +# +# 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. + +PREFIX=/usr/local +BINDIR=${PREFIX}/bin +LIBDIR=${PREFIX}/lib +INCDIR=${PREFIX}/include +CC = gcc +#CFLAGS = -O3 -I$(HOME)/include +CFLAGS = -g -I$(HOME)/include + +ALL = reed_sol_test_01 + +all: $(ALL) + +clean: + rm -f core *.o $(ALL) a.out cauchy.h cauchy.c liberation.h liberation.c reed_sol.c reed_sol.h\ + jerasure.c jerasure.h galois.c galois.h + +.SUFFIXES: .c .o +.c.o: + $(CC) $(CFLAGS) -c $*.c + +liberation.h: ../liberation.h + rm -f liberation.h ; cp ../liberation.h . ; chmod 0444 liberation.h + +liberation.c: ../liberation.c + rm -f liberation.c ; cp ../liberation.c . ; chmod 0444 liberation.c + +cauchy.h: ../cauchy.h + rm -f cauchy.h ; cp ../cauchy.h . ; chmod 0444 cauchy.h + +cauchy.c: ../cauchy.c + rm -f cauchy.c ; cp ../cauchy.c . ; chmod 0444 cauchy.c + +reed_sol.h: ../reed_sol.h + rm -f reed_sol.h ; cp ../reed_sol.h . ; chmod 0444 reed_sol.h + +reed_sol.c: ../reed_sol.c + rm -f reed_sol.c ; cp ../reed_sol.c . ; chmod 0444 reed_sol.c + +jerasure.h: ../jerasure.h + rm -f jerasure.h ; cp ../jerasure.h . ; chmod 0444 jerasure.h + +jerasure.c: ../jerasure.c + rm -f jerasure.c ; cp ../jerasure.c . ; chmod 0444 jerasure.c + +galois.h: ../galois.h + rm -f galois.h ; cp ../galois.h . ; chmod 0444 galois.h + +galois.c: ../galois.c + rm -f galois.c ; cp ../galois.c . ; chmod 0444 galois.c + +galois.o ${LIBDIR}/gf_complete.a: galois.h +jerasure.o: jerasure.h galois.h + +reed_sol_test_01.o: galois.h reed_sol.h jerasure.h +reed_sol_test_01: reed_sol_test_01.o galois.o ${LIBDIR}/gf_complete.a jerasure.o reed_sol.o + $(CC) $(CFLAGS) -o reed_sol_test_01 reed_sol_test_01.o reed_sol.o jerasure.o galois.o ${LIBDIR}/gf_complete.a + diff --git a/Test/reed_sol_test_01.c b/Test/reed_sol_test_01.c new file mode 100755 index 0000000..50570e2 --- /dev/null +++ b/Test/reed_sol_test_01.c @@ -0,0 +1,180 @@ +/* Examples/reed_sol_01.c +Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques + +Revision 1.2A +May 24, 2011 + +James S. Plank +Department of Electrical Engineering and Computer Science +University of Tennessee +Knoxville, TN 37996 +plank@cs.utk.edu + +Copyright (c) 2011, James S. Plank +All rights reserved. + +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. + + + */ + + +/* + revised by S. Simmerman + 2/25/08 +*/ +#include +#include +#include +#include +#include "jerasure.h" +#include "reed_sol.h" + +#define BUFSIZE 4096 + +#define talloc(type, num) (type *) malloc(sizeof(type)*(num)) + +usage(char *s) +{ + fprintf(stderr, "usage: reed_sol_test_01 k m w [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. It sets up a classic\n"); + fprintf(stderr, " 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, " 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; +} + +static void fill_buffer(unsigned char *buf, int size) +{ + int i; + + buf[0] = (char)(lrand48() % 256); + + for (i=1; i < size; i++) { + buf[i] = ((buf[i-1] + i) % 256); + } +} + +int main(int argc, char **argv) +{ + long l; + int k, w, i, j, m; + int *matrix; + char **data, **coding, **old_values; + int *erasures, *erased; + int *decoding_matrix, *dm_ids; + gf_t *gf = NULL; + + 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 != 8 && w != 16 && w != 32)) usage("Bad w"); + if (w <= 16 && k + m > (1 << w)) usage("k + m is too big"); + + srand48(time(0)); + + gf = get_gf(w, argc, argv, 4); + + 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("Last m rows of the Distribution Matrix:\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); + fill_buffer(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; + l = 0; + for (i = 0; i < m; ) { + erasures[i] = ((unsigned int)lrand48())%(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); + } + } + } + + return 0; +} diff --git a/Test/test_all_gfs.sh b/Test/test_all_gfs.sh new file mode 100755 index 0000000..ea658ba --- /dev/null +++ b/Test/test_all_gfs.sh @@ -0,0 +1,39 @@ +GF_COMPLETE_DIR=/usr/local/bin +GF_METHODS=${GF_COMPLETE_DIR}/gf_methods +k=12 +m=3 + +# Test all w=8 +${GF_METHODS} | awk -F: '{ if ($1 == "w=8") print $2; }' | +while read method; do + echo "Testing ${k} ${m} 8 ${method}" + ./reed_sol_test_01 ${k} ${m} 8 ${method} + if [[ $? != "0" ]]; then + echo "Failed test for ${k} ${m} 8 ${method}" + exit 1 + fi +done + +# Test all w=16 +${GF_METHODS} | grep -v 'TABLE' | awk -F: '{ if ($1 == "w=16") print $2; }' | +while read method; do + echo "Testing ${k} ${m} 16 ${method}" + ./reed_sol_test_01 ${k} ${m} 16 ${method} + if [[ $? != "0" ]]; then + echo "Failed test for ${k} ${m} 16 ${method}" + exit 1 + fi +done + +# Test all w=32 +${GF_METHODS} | awk -F: '{ if ($1 == "w=32") print $2; }' | +while read method; do + echo "Testing ${k} ${m} 32 ${method}" + ./reed_sol_test_01 ${k} ${m} 32 ${method} + if [[ $? != "0" ]]; then + echo "Failed test for ${k} ${m} 32 ${method}" + exit 1 + fi +done + +echo "Passed all tests!" diff --git a/galois.c b/galois.c index e16d072..8c8e9c7 100755 --- a/galois.c +++ b/galois.c @@ -55,18 +55,140 @@ POSSIBILITY OF SUCH DAMAGE. #define MAX_GF_INSTANCES 128 gf_t *gfp_array[MAX_GF_INSTANCES] = { 0 }; -static void -galois_init_field(int w) +gf_t *galois_get_field_ptr(int w) { - if (w <= 0 || w > 128) { + if (gfp_array[w] != NULL) { + return gfp_array[w]; + } + + return NULL; +} + +int galois_init_base_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; + int ret; + + if (w <= 0 || w > 32) { fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w); exit(1); } - if (w > 32 && (w != 64 || w != 128)) { + 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); + exit(1); + } + + scratch_memory = malloc(scratch_size); + if (!scratch_memory) { + fprintf(stderr, "ERROR -- cannot get scratch memory for base field w=%d\n", w); + exit(1); + } + + /* + * Properly free up the old field + */ + if (gfp_array[w] != NULL) { + gf_free(gfp_array[w], 0); + } + + gfp_array[w] = (gf_t*)malloc(sizeof(gf_t)); + if (gfp_array[w] == NULL) { + fprintf(stderr, "ERROR -- cannot allocate memory for Galois field w=%d\n", w); + exit(1); + } + + if(!gf_init_hard(gfp_array[w], + 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); exit(1); } + return 0; +} + +int galois_init_composite_field(int w, + int region_type, + int divide_type, + uint64_t prim_poly, + int arg1, + int arg2, + gf_t* base_gf) +{ + int scratch_size; + void *scratch_memory; + int ret; + + if (w <= 0 || w > 32) { + fprintf(stderr, "ERROR -- cannot init composite field for w=%d\n", w); + exit(1); + } + + scratch_size = gf_scratch_size(w, GF_MULT_COMPOSITE, region_type, divide_type, arg1, arg2); + if (!scratch_size) { + fprintf(stderr, "ERROR -- cannot get scratch size for composite field w=%d\n", w); + exit(1); + } + + scratch_memory = malloc(scratch_size); + if (!scratch_memory) { + fprintf(stderr, "ERROR -- cannot get scratch memory for composite field w=%d\n", w); + exit(1); + } + + /* + * Properly free up the old field + */ + if (gfp_array[w] != NULL) { + gf_free(gfp_array[w], 1); + } + + gfp_array[w] = (gf_t*)malloc(sizeof(gf_t)); + if (gfp_array[w] == NULL) { + fprintf(stderr, "ERROR -- cannot allocate memory for composite field w=%d\n", w); + exit(1); + } + + if(!gf_init_hard(gfp_array[w], + w, + GF_MULT_COMPOSITE, + region_type, + divide_type, + prim_poly, + arg1, + arg2, + base_gf, + scratch_memory)) + { + fprintf(stderr, "ERROR -- cannot init default composite field for w=%d\n", w); + exit(1); + } + return 0; +} + +static void galois_init_default_field(int w) +{ + if (w <= 0 || w > 32) { + fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w); + exit(1); + } + if (gfp_array[w] == NULL) { gfp_array[w] = (gf_t*)malloc(sizeof(gf_t)); if (gfp_array[w] == NULL) { @@ -74,48 +196,70 @@ galois_init_field(int w) exit(1); } } - - if (w == 16) { - if (!gf_init_hard(gfp_array[w], w, GF_MULT_SPLIT_TABLE, GF_REGION_ALTMAP, GF_DIVIDE_DEFAULT, - 0, 16, 4, NULL, NULL)) { - fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w); - exit(1); - } - } if (!gf_init_easy(gfp_array[w], w)) { fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w); exit(1); } } + +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 > 128) { - fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w); + if (w <= 0 || w > 32) { + fprintf(stderr, "ERROR -- cannot support Galois field for w=%d\n", w); exit(1); } - if (w > 32 && (w != 64 || w != 128)) { - fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w); + if (!is_valid_gf(gf, w)) { + fprintf(stderr, "ERROR -- overriding with invalid Galois field for w=%d\n", w); exit(1); } - /* - * TODO: Sanity check on gf? - */ 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_field(w); + galois_init_default_field(w); } - return gfp_array[w]->multiply.w32(gfp_array[w], x, y); + 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); + } } int galois_single_divide(int x, int y, int w) @@ -124,10 +268,14 @@ int galois_single_divide(int x, int y, int w) if (y == 0) return -1; if (gfp_array[w] == NULL) { - galois_init_field(w); + galois_init_default_field(w); } - return gfp_array[w]->divide.w32(gfp_array[w], x, y); + 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); + } } void galois_w08_region_multiply(char *region, /* Region to multiply */ @@ -137,7 +285,7 @@ void galois_w08_region_multiply(char *region, /* Region to multiply */ int add) { if (gfp_array[8] == NULL) { - galois_init_field(8); + galois_init_default_field(8); } gfp_array[8]->multiply_region.w32(gfp_array[8], region, r2, multby, nbytes, add); } @@ -149,7 +297,7 @@ void galois_w16_region_multiply(char *region, /* Region to multiply */ int add) { if (gfp_array[16] == NULL) { - galois_init_field(16); + galois_init_default_field(16); } gfp_array[16]->multiply_region.w32(gfp_array[16], region, r2, multby, nbytes, add); } @@ -162,15 +310,39 @@ void galois_w32_region_multiply(char *region, /* Region to multiply */ int add) { if (gfp_array[32] == NULL) { - galois_init_field(32); + galois_init_default_field(32); } gfp_array[32]->multiply_region.w32(gfp_array[32], region, r2, multby, nbytes, add); } -void galois_region_xor( char *r1, /* Region 1 */ - char *r2, /* Region 2 */ - char *r3, /* Sum region (r3 = r1 ^ r2) -- can be r1 or r2 */ - int nbytes) /* Number of bytes in region */ +void galois_w8_region_xor(void *src, void *dest, int nbytes) +{ + if (gfp_array[8] == NULL) { + galois_init_default_field(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_default_field(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_default_field(32); + } + gfp_array[32]->multiply_region.w32(gfp_array[32], src, dest, 1, nbytes, 1); +} + +void galois_region_xor(char *r1, /* Region 1 */ + char *r2, /* Region 2 */ + char *r3, /* Sum region (r3 = r1 ^ r2) -- can be r1 or r2 */ + int nbytes) /* Number of bytes in region */ { long *l1; long *l2; diff --git a/galois.h b/galois.h index e246220..4a838f6 100755 --- a/galois.h +++ b/galois.h @@ -88,4 +88,23 @@ void galois_w32_region_multiply(char *region, /* Region to multiply */ Otherwise region is overwritten */ int add); /* If (r2 != NULL && add) the produce is XOR'd with r2 */ +int galois_init_base_field(int w, + int mult_type, + int region_type, + int divide_type, + uint64_t prim_poly, + int arg1, + int arg2); + +int galois_init_composite_field(int w, + int region_type, + int divide_type, + uint64_t prim_poly, + int arg1, + int arg2, + gf_t* base_gf); + +gf_t * galois_get_field_ptr(int w); + + #endif