diff --git a/Makefile.am b/Makefile.am index 01a1bc8d..1d1a6a5e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,7 +10,7 @@ snapraid_SOURCES = \ raid/x86.c \ raid/intz.c \ raid/x86z.c \ - raid/sort.c \ + raid/helper.c \ raid/memory.c \ raid/test.c \ raid/tag.c \ @@ -43,6 +43,7 @@ mktables_SOURCES = \ noinst_HEADERS = \ raid/raid.h \ + raid/helper.h \ raid/internal.h \ raid/cpu.h \ raid/gf.h \ diff --git a/raid/helper.c b/raid/helper.c new file mode 100644 index 00000000..db868076 --- /dev/null +++ b/raid/helper.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 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. + */ + +#include "internal.h" + +#define RAID_SWAP(a, b) \ + do { \ + if (v[a] > v[b]) { \ + int t = v[a]; \ + v[a] = v[b]; \ + v[b] = t; \ + } \ + } while (0) + +void raid_sort(int n, int *v) +{ + /* sorting networks generated with Batcher's Merge-Exchange */ + switch (n) { + case 2: + RAID_SWAP(0, 1); + break; + case 3: + RAID_SWAP(0, 2); + RAID_SWAP(0, 1); + RAID_SWAP(1, 2); + break; + case 4: + RAID_SWAP(0, 2); + RAID_SWAP(1, 3); + RAID_SWAP(0, 1); + RAID_SWAP(2, 3); + RAID_SWAP(1, 2); + break; + case 5: + RAID_SWAP(0, 4); + RAID_SWAP(0, 2); + RAID_SWAP(1, 3); + RAID_SWAP(2, 4); + RAID_SWAP(0, 1); + RAID_SWAP(2, 3); + RAID_SWAP(1, 4); + RAID_SWAP(1, 2); + RAID_SWAP(3, 4); + break; + case 6: + RAID_SWAP(0, 4); + RAID_SWAP(1, 5); + RAID_SWAP(0, 2); + RAID_SWAP(1, 3); + RAID_SWAP(2, 4); + RAID_SWAP(3, 5); + RAID_SWAP(0, 1); + RAID_SWAP(2, 3); + RAID_SWAP(4, 5); + RAID_SWAP(1, 4); + RAID_SWAP(1, 2); + RAID_SWAP(3, 4); + break; + } +} + +void raid_insert(int n, int *v, int i) +{ + /* we don't use binary search because this is intended */ + /* for very small vectors and we want to optimize the case */ + /* of elements inserted already in order */ + + /* insert at the end */ + v[n] = i; + + /* swap until in the correct position */ + while (n > 0 && v[n-1] > v[n]) { + /* swap */ + int t = v[n-1]; + v[n-1] = v[n]; + v[n] = t; + + /* previous position */ + --n; + } +} + diff --git a/raid/helper.h b/raid/helper.h new file mode 100644 index 00000000..bf682882 --- /dev/null +++ b/raid/helper.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 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. + */ + +#ifndef __RAID_HELPER_H +#define __RAID_HELPER_H + +/** + * Inserts an integer in a sorted vector. + * + * This function can be used to insert indexes in order, ready to be used for + * calling raid_rec(). + * + * @n Number of integers currently in the vector. + * @v Vector of integers already sorted. + * It must have extra space for the new elemet at the end. + * @i Value to insert. + */ +void raid_insert(int n, int *v, int i); + +/** + * Sorts a small vector of integers. + * + * If you have indexes not in order, you can use this function to sort them + * before calling raid_rec(). + * + * @n Number of integers. No more than RAID_PARITY_MAX. + * @v Vector of integers. + */ +void raid_sort(int n, int *v); + +#endif + diff --git a/raid/internal.h b/raid/internal.h index ff3e138b..4e83b22f 100644 --- a/raid/internal.h +++ b/raid/internal.h @@ -22,7 +22,7 @@ #define BUG_ON(a) assert(!(a)) /* - * Includes the main header. + * Includes the headers. */ #include "raid.h" diff --git a/raid/raid.h b/raid/raid.h index 0b915022..ca329bbb 100644 --- a/raid/raid.h +++ b/raid/raid.h @@ -158,16 +158,5 @@ void raid_rec(int nr, int *ir, int nd, int np, size_t size, void **v); */ void raid_rec_dataonly(int nr, int *id, int *ip, int nd, size_t size, void **v); -/** - * Sorts a small vector of integers. - * - * If you have block indexes not in order, you can use this function to sort - * them before calling raid_rec(). - * - * @n Number of integers. No more than RAID_PARITY_MAX. - * @v Vector of integers. - */ -void raid_sort(int n, int *v); - #endif diff --git a/raid/tag.c b/raid/tag.c new file mode 100644 index 00000000..e3042c88 --- /dev/null +++ b/raid/tag.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 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. + */ + +#include "internal.h" + +static struct raid_func { + const char *name; + void *p; +} RAID_FUNC[] = { + { "int8", raid_gen3_int8 }, + { "int8", raid_gen4_int8 }, + { "int8", raid_gen5_int8 }, + { "int8", raid_gen6_int8 }, + { "int32", raid_gen1_int32 }, + { "int64", raid_gen1_int64 }, + { "int32", raid_gen2_int32 }, + { "int64", raid_gen2_int64 }, + { "int32", raid_genz_int32 }, + { "int64", raid_genz_int64 }, + { "int8", raid_rec1_int8 }, + { "int8", raid_rec2_int8 }, + { "int8", raid_recX_int8 }, + +#ifdef CONFIG_X86 + { "sse2", raid_gen1_sse2 }, + { "sse2", raid_gen2_sse2 }, + { "sse2", raid_genz_sse2 }, + { "ssse3", raid_gen3_ssse3 }, + { "ssse3", raid_gen4_ssse3 }, + { "ssse3", raid_gen5_ssse3 }, + { "ssse3", raid_gen6_ssse3 }, + { "ssse3", raid_rec1_ssse3 }, + { "ssse3", raid_rec2_ssse3 }, + { "ssse3", raid_recX_ssse3 }, +#endif + +#ifdef CONFIG_X86_64 + { "sse2e", raid_gen2_sse2ext }, + { "sse2e", raid_genz_sse2ext }, + { "ssse3e", raid_gen3_ssse3ext }, + { "ssse3e", raid_gen4_ssse3ext }, + { "ssse3e", raid_gen5_ssse3ext }, + { "ssse3e", raid_gen6_ssse3ext }, +#endif + { 0, 0 } +}; + +static const char *raid_tag(void *func) +{ + struct raid_func *i = RAID_FUNC; + while (i->name != 0) { + if (i->p == func) + return i->name; + ++i; + } + return "unknown"; +} + +const char *raid_gen1_tag(void) +{ + return raid_tag(raid_gen_ptr[0]); +} + +const char *raid_gen2_tag(void) +{ + return raid_tag(raid_gen_ptr[1]); +} + +const char *raid_genz_tag(void) +{ + return raid_tag(raid_genz_ptr); +} + +const char *raid_gen3_tag(void) +{ + return raid_tag(raid_gen_ptr[2]); +} + +const char *raid_gen4_tag(void) +{ + return raid_tag(raid_gen_ptr[3]); +} + +const char *raid_gen5_tag(void) +{ + return raid_tag(raid_gen_ptr[4]); +} + +const char *raid_gen6_tag(void) +{ + return raid_tag(raid_gen_ptr[5]); +} + +const char *raid_rec1_tag(void) +{ + return raid_tag(raid_rec_ptr[0]); +} + +const char *raid_rec2_tag(void) +{ + return raid_tag(raid_rec_ptr[1]); +} + +const char *raid_recX_tag(void) +{ + return raid_tag(raid_rec_ptr[2]); +} + diff --git a/raid/test.c b/raid/test.c index 7b62f62b..b7086e97 100644 --- a/raid/test.c +++ b/raid/test.c @@ -13,6 +13,7 @@ */ #include "internal.h" +#include "helper.h" #include "cpu.h" #include "combo.h" #include "memory.h" @@ -76,6 +77,31 @@ int raid_test_combo(void) return 0; } +int raid_test_insert(void) +{ + int p[RAID_PARITY_MAX]; + int r; + + for (r = 1; r <= RAID_PARITY_MAX; ++r) { + permutation_first(r, RAID_PARITY_MAX, p); + do { + int i[RAID_PARITY_MAX]; + int j; + + /* insert in order */ + for (j = 0; j < r; ++j) + raid_insert(j, i, p[j]); + + /* check order */ + for (j = 1; j < r; ++j) + if (i[j-1] > i[j]) + return -1; + } while (permutation_next(r, RAID_PARITY_MAX, p)); + } + + return 0; +} + int raid_test_sort(void) { int p[RAID_PARITY_MAX]; diff --git a/raid/test.h b/raid/test.h index 372e70a1..6d902c7f 100644 --- a/raid/test.h +++ b/raid/test.h @@ -16,7 +16,16 @@ #define __RAID_TEST_H /** - * Tests sorting functions. + * Tests insertion function. + * + * Test raid_insert() with all the possible combinations of elements to insert. + * + * Returns 0 on success. + */ +int raid_test_insert(void); + +/** + * Tests sorting function. * * Test raid_sort() with all the possible combinations of elements to sort. *