Make bitonic work for non powers of 2 (#24)
This commit is contained in:
parent
ca5946b92a
commit
03c1305f57
@ -15,6 +15,39 @@
|
|||||||
|
|
||||||
#include "swap.h"
|
#include "swap.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verificar si x es de 2^n
|
||||||
|
* @param x El valor a verificar
|
||||||
|
* @return Retorna 1 si es de 2^n ó 0 al contrario;
|
||||||
|
*/
|
||||||
|
int power_of_two(int n) {
|
||||||
|
if (n == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (n != 1) {
|
||||||
|
if (n % 2 != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
n = n / 2;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buscar un valor que es de potencia de 2 pero menor que n
|
||||||
|
* @param n El valor de n
|
||||||
|
* @return Un potencia de 2 que es menor que n
|
||||||
|
*/
|
||||||
|
int greatest_power_of_two_less_than(int n) {
|
||||||
|
int k = 1;
|
||||||
|
while (k > 0 && k < n) {
|
||||||
|
k = (int) ((unsigned int) k << 1);
|
||||||
|
}
|
||||||
|
k = (int) ((unsigned int) k >> 1);
|
||||||
|
return (int) k;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comparar y intercambiar los valores para darle orden
|
* Comparar y intercambiar los valores para darle orden
|
||||||
* @param i El primer indice a comparar
|
* @param i El primer indice a comparar
|
||||||
@ -31,16 +64,16 @@ void compare(int i, int j, int dir, int *array) { //
|
|||||||
/**
|
/**
|
||||||
* Unir la secuencia
|
* Unir la secuencia
|
||||||
* @param low El parte inferior
|
* @param low El parte inferior
|
||||||
* @param c El parte superior
|
* @param c El parte superior n
|
||||||
* @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
|
* @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
|
||||||
* @param array El array a ordenar
|
* @param array El array a ordenar
|
||||||
*/
|
*/
|
||||||
void bitonicmerge(int low, int c, int dir, int *array) {
|
void bitonicmerge(int low, int n, int dir, int *array) {
|
||||||
int i;
|
int i;
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
if (c > 1){
|
if (n > 1) {
|
||||||
k = c / 2;
|
k = n / 2;
|
||||||
for (i = low; i < low + k; i++){
|
for (i = low; i < low + k; i++){
|
||||||
compare(i, i + k, dir, array);
|
compare(i, i + k, dir, array);
|
||||||
}
|
}
|
||||||
@ -50,20 +83,59 @@ void bitonicmerge(int low, int c, int dir, int *array) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generar la secuencia bitonica en forma de piramide
|
* Unir la secuencia cuando n no es de potencia 2
|
||||||
* @param low El parte inferior
|
* @param low El parte inferior
|
||||||
* @param c El parte superior
|
* @param c El parte superior n
|
||||||
* @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
|
* @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
|
||||||
* @param array El array a ordenar
|
* @param array El array a ordenar
|
||||||
*/
|
*/
|
||||||
void recbitonic(int low, int c, int dir, int *array) {
|
void bitonicmerge_no2(int low, int n, int dir, int *array) {
|
||||||
|
int i;
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
if (c > 1){
|
if (n > 1) {
|
||||||
k = c / 2;
|
k = greatest_power_of_two_less_than(n);
|
||||||
|
for (i = low; i < low + n-k; i++){
|
||||||
|
compare(i, i + k, dir, array);
|
||||||
|
}
|
||||||
|
bitonicmerge_no2(low, k, dir, array);
|
||||||
|
bitonicmerge_no2(low + k, n - k, dir, array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generar la secuencia bitonica en forma de piramide
|
||||||
|
* @param low El parte inferior
|
||||||
|
* @param c El parte superior n
|
||||||
|
* @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
|
||||||
|
* @param array El array a ordenar
|
||||||
|
*/
|
||||||
|
void recbitonic(int low, int n, int dir, int *array) {
|
||||||
|
int k;
|
||||||
|
|
||||||
|
if (n > 1){
|
||||||
|
k = n / 2;
|
||||||
recbitonic(low, k, 1, array);
|
recbitonic(low, k, 1, array);
|
||||||
recbitonic(low + k, k, 0, array);
|
recbitonic(low + k, k, 0, array);
|
||||||
bitonicmerge(low, c, dir, array);
|
bitonicmerge(low, n, dir, array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generar la secuencia bitonica en forma de piramide cuando n no es de potencia 2
|
||||||
|
* @param low El parte inferior
|
||||||
|
* @param c El parte superior n
|
||||||
|
* @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
|
||||||
|
* @param array El array a ordenar
|
||||||
|
*/
|
||||||
|
void recbitonic_no2(int low, int n, int dir, int *array) {
|
||||||
|
int k;
|
||||||
|
|
||||||
|
if (n > 1){
|
||||||
|
k = n / 2;
|
||||||
|
recbitonic_no2(low, k, !dir, array);
|
||||||
|
recbitonic_no2(low + k, n - k, dir, array);
|
||||||
|
bitonicmerge_no2(low, n, dir, array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +146,12 @@ void recbitonic(int low, int c, int dir, int *array) {
|
|||||||
* @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
|
* @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
|
||||||
*/
|
*/
|
||||||
void sort(int *array, int n, int dir) {
|
void sort(int *array, int n, int dir) {
|
||||||
recbitonic(0, n, dir, array);
|
if (power_of_two(n)) {
|
||||||
|
recbitonic(0, n, dir, array);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
recbitonic_no2(0, n, dir, array);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,5 +160,5 @@ void sort(int *array, int n, int dir) {
|
|||||||
* @param n El tamaño del array
|
* @param n El tamaño del array
|
||||||
*/
|
*/
|
||||||
void bitonic_sort(int *array, int n) {
|
void bitonic_sort(int *array, int n) {
|
||||||
sort(array, n, 1);
|
sort(array, n, 1);
|
||||||
}
|
}
|
||||||
|
77
test/test.c
77
test/test.c
@ -52,7 +52,8 @@ void cleanup() {
|
|||||||
* El programa de test
|
* El programa de test
|
||||||
*/
|
*/
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
int n = 32768;
|
int n = 50000;
|
||||||
|
int n2 = 32768;
|
||||||
int i;
|
int i;
|
||||||
int gen;
|
int gen;
|
||||||
int pass;
|
int pass;
|
||||||
@ -99,7 +100,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
// Prepare for sort tests
|
// Prepare for sort tests
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
test_case[i] = gen_rand(-100, 100);
|
test_case[i] = gen_rand(-1000000, 1000000);
|
||||||
}
|
}
|
||||||
memcpy(qarray, test_case, sizeof(int) * n);
|
memcpy(qarray, test_case, sizeof(int) * n);
|
||||||
qsort(qarray, n, sizeof(int), compar);
|
qsort(qarray, n, sizeof(int), compar);
|
||||||
@ -156,25 +157,6 @@ int main(int argc, char **argv) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pass) {
|
|
||||||
fprintf(stdout, "pass\n");
|
|
||||||
passed++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test bitonic sort
|
|
||||||
pass = 1;
|
|
||||||
memcpy(test_array, test_case, sizeof(int) * n);
|
|
||||||
fprintf(stdout, "\tbitonic sort: ");
|
|
||||||
fflush(stdout);
|
|
||||||
bitonic_sort(test_array, n);
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
if (test_array[i] != qarray[i]) {
|
|
||||||
fprintf(stdout, "fail\n");
|
|
||||||
failed++;
|
|
||||||
pass = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pass) {
|
if (pass) {
|
||||||
fprintf(stdout, "pass\n");
|
fprintf(stdout, "pass\n");
|
||||||
passed++;
|
passed++;
|
||||||
@ -218,6 +200,59 @@ int main(int argc, char **argv) {
|
|||||||
passed++;
|
passed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test bitonic sort without 2^n
|
||||||
|
pass = 1;
|
||||||
|
memcpy(test_array, test_case, sizeof(int) * n);
|
||||||
|
fprintf(stdout, "\tbitonic sort: ");
|
||||||
|
fflush(stdout);
|
||||||
|
bitonic_sort(test_array, n);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (test_array[i] != qarray[i]) {
|
||||||
|
fprintf(stdout, "fail\n");
|
||||||
|
failed++;
|
||||||
|
pass = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pass) {
|
||||||
|
fprintf(stdout, "pass\n");
|
||||||
|
passed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test bitonic sort with 2^n
|
||||||
|
pass = 1;
|
||||||
|
int *bitonic_test_case = malloc(sizeof(int) * n2);
|
||||||
|
if (bitonic_test_case == NULL) {
|
||||||
|
fprintf(stderr, "Error: Out of heap space!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
int *bitonic_test_array = malloc(sizeof(int) * n2);
|
||||||
|
if (bitonic_test_array == NULL) {
|
||||||
|
fprintf(stderr, "Error: Out of heap space!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
bitonic_test_case[i] = gen_rand(-1000000, 1000000);
|
||||||
|
}
|
||||||
|
memcpy(qarray, bitonic_test_case, sizeof(int) * n2);
|
||||||
|
qsort(qarray, n2, sizeof(int), compar);
|
||||||
|
memcpy(bitonic_test_array, bitonic_test_case, sizeof(int) * n2);
|
||||||
|
fprintf(stdout, "\tbitonic sort 2^n: ");
|
||||||
|
fflush(stdout);
|
||||||
|
bitonic_sort(bitonic_test_array, n2);
|
||||||
|
for (i = 0; i < n2; i++) {
|
||||||
|
if (bitonic_test_array[i] != qarray[i]) {
|
||||||
|
fprintf(stdout, "fail\n");
|
||||||
|
failed++;
|
||||||
|
pass = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pass) {
|
||||||
|
fprintf(stdout, "pass\n");
|
||||||
|
passed++;
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(stdout, "%d tests passed\n", passed);
|
fprintf(stdout, "%d tests passed\n", passed);
|
||||||
fprintf(stdout, "%d tests failed\n", failed);
|
fprintf(stdout, "%d tests failed\n", failed);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user